<article class="markdown-body entry-content p-5" itemprop="text"><h1><a id="user-content-gin-web-framework" class="anchor" aria-hidden="true" href="#gin-web-framework"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gin Web Framework</h1>
    <p><a target="_blank" rel="noopener noreferrer" href="https://raw.githubusercontent.com/gin-gonic/logo/master/color.png"><img align="right" width="159px" src="https://raw.githubusercontent.com/gin-gonic/logo/master/color.png" style="max-width:100%;"></a></p>
    <p><a href="https://travis-ci.org/gin-gonic/gin" rel="nofollow"><img src="https://camo.githubusercontent.com/1e302ca5edd246dbec5dce477b94313881654733/68747470733a2f2f7472617669732d63692e6f72672f67696e2d676f6e69632f67696e2e737667" alt="Build Status" data-canonical-src="https://travis-ci.org/gin-gonic/gin.svg" style="max-width:100%;"></a>
        <a href="https://codecov.io/gh/gin-gonic/gin" rel="nofollow"><img src="https://camo.githubusercontent.com/4cffe2606f8cf24ea4a1f9f7491ba02a1dd057c6/68747470733a2f2f636f6465636f762e696f2f67682f67696e2d676f6e69632f67696e2f6272616e63682f6d61737465722f67726170682f62616467652e737667" alt="codecov" data-canonical-src="https://codecov.io/gh/gin-gonic/gin/branch/master/graph/badge.svg" style="max-width:100%;"></a>
        <a href="https://goreportcard.com/report/github.com/gin-gonic/gin" rel="nofollow"><img src="https://camo.githubusercontent.com/5ad116181da0c08023ebb577817f4abc9fa1b391/68747470733a2f2f676f7265706f7274636172642e636f6d2f62616467652f6769746875622e636f6d2f67696e2d676f6e69632f67696e" alt="Go Report Card" data-canonical-src="https://goreportcard.com/badge/github.com/gin-gonic/gin" style="max-width:100%;"></a>
        <a href="https://godoc.org/github.com/gin-gonic/gin" rel="nofollow"><img src="https://camo.githubusercontent.com/8c3edc352f01db1a95ccff1d08618556fb6ba8f3/68747470733a2f2f676f646f632e6f72672f6769746875622e636f6d2f67696e2d676f6e69632f67696e3f7374617475732e737667" alt="GoDoc" data-canonical-src="https://godoc.org/github.com/gin-gonic/gin?status.svg" style="max-width:100%;"></a>
        <a href="https://gitter.im/gin-gonic/gin?utm_source=badge&amp;utm_medium=badge&amp;utm_campaign=pr-badge&amp;utm_content=badge" rel="nofollow"><img src="https://camo.githubusercontent.com/da2edb525cde1455a622c58c0effc3a90b9a181c/68747470733a2f2f6261646765732e6769747465722e696d2f4a6f696e253230436861742e737667" alt="Join the chat at https://gitter.im/gin-gonic/gin" data-canonical-src="https://badges.gitter.im/Join%20Chat.svg" style="max-width:100%;"></a>
        <a href="https://sourcegraph.com/github.com/gin-gonic/gin?badge" rel="nofollow"><img src="https://camo.githubusercontent.com/0a19b0e2caff819736338c5b7709943eac5df300/68747470733a2f2f736f7572636567726170682e636f6d2f6769746875622e636f6d2f67696e2d676f6e69632f67696e2f2d2f62616467652e737667" alt="Sourcegraph" data-canonical-src="https://sourcegraph.com/github.com/gin-gonic/gin/-/badge.svg" style="max-width:100%;"></a>
        <a href="https://www.codetriage.com/gin-gonic/gin" rel="nofollow"><img src="https://camo.githubusercontent.com/4493347a01c52f7a0319127c610187438219305f/68747470733a2f2f7777772e636f64657472696167652e636f6d2f67696e2d676f6e69632f67696e2f6261646765732f75736572732e737667" alt="Open Source Helpers" data-canonical-src="https://www.codetriage.com/gin-gonic/gin/badges/users.svg" style="max-width:100%;"></a>
        <a href="https://github.com/gin-gonic/gin/releases"><img src="https://camo.githubusercontent.com/9dcdba8103af84591a6df2626476bb973daa858d/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f72656c656173652f67696e2d676f6e69632f67696e2e7376673f7374796c653d666c61742d737175617265" alt="Release" data-canonical-src="https://img.shields.io/github/release/gin-gonic/gin.svg?style=flat-square" style="max-width:100%;"></a></p>
    <p>Gin is a web framework written in Go (Golang). It features a martini-like API with much better performance, up to 40 times faster thanks to <a href="https://github.com/julienschmidt/httprouter">httprouter</a>. If you need performance and good productivity, you will love Gin.</p>
    <h2><a id="user-content-contents" class="anchor" aria-hidden="true" href="#contents"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Contents</h2>
    <ul>
        <li><a href="#installation">Installation</a></li>
        <li><a href="#prerequisite">Prerequisite</a></li>
        <li><a href="#quick-start">Quick start</a></li>
        <li><a href="#benchmarks">Benchmarks</a></li>
        <li><a href="#gin-v1-stable">Gin v1.stable</a></li>
        <li><a href="#build-with-jsoniter">Build with jsoniter</a></li>
        <li><a href="#api-examples">API Examples</a>
            <ul>
                <li><a href="#using-get-post-put-patch-delete-and-options">Using GET,POST,PUT,PATCH,DELETE and OPTIONS</a></li>
                <li><a href="#parameters-in-path">Parameters in path</a></li>
                <li><a href="#querystring-parameters">Querystring parameters</a></li>
                <li><a href="#multiparturlencoded-form">Multipart/Urlencoded Form</a></li>
                <li><a href="#another-example-query--post-form">Another example: query + post form</a></li>
                <li><a href="#map-as-querystring-or-postform-parameters">Map as querystring or postform parameters</a></li>
                <li><a href="#upload-files">Upload files</a></li>
                <li><a href="#grouping-routes">Grouping routes</a></li>
                <li><a href="#blank-gin-without-middleware-by-default">Blank Gin without middleware by default</a></li>
                <li><a href="#using-middleware">Using middleware</a></li>
                <li><a href="#how-to-write-log-file">How to write log file</a></li>
                <li><a href="#custom-log-format">Custom Log Format</a></li>
                <li><a href="#model-binding-and-validation">Model binding and validation</a></li>
                <li><a href="#custom-validators">Custom Validators</a></li>
                <li><a href="#only-bind-query-string">Only Bind Query String</a></li>
                <li><a href="#bind-query-string-or-post-data">Bind Query String or Post Data</a></li>
                <li><a href="#bind-uri">Bind Uri</a></li>
                <li><a href="#bind-header">Bind Header</a></li>
                <li><a href="#bind-html-checkboxes">Bind HTML checkboxes</a></li>
                <li><a href="#multiparturlencoded-binding">Multipart/Urlencoded binding</a></li>
                <li><a href="#xml-json-yaml-and-protobuf-rendering">XML, JSON, YAML and ProtoBuf rendering</a></li>
                <li><a href="#jsonp">JSONP rendering</a></li>
                <li><a href="#serving-static-files">Serving static files</a></li>
                <li><a href="#serving-data-from-reader">Serving data from reader</a></li>
                <li><a href="#html-rendering">HTML rendering</a></li>
                <li><a href="#multitemplate">Multitemplate</a></li>
                <li><a href="#redirects">Redirects</a></li>
                <li><a href="#custom-middleware">Custom Middleware</a></li>
                <li><a href="#using-basicauth-middleware">Using BasicAuth() middleware</a></li>
                <li><a href="#goroutines-inside-a-middleware">Goroutines inside a middleware</a></li>
                <li><a href="#custom-http-configuration">Custom HTTP configuration</a></li>
                <li><a href="#support-lets-encrypt">Support Let's Encrypt</a></li>
                <li><a href="#run-multiple-service-using-gin">Run multiple service using Gin</a></li>
                <li><a href="#graceful-restart-or-stop">Graceful restart or stop</a></li>
                <li><a href="#build-a-single-binary-with-templates">Build a single binary with templates</a></li>
                <li><a href="#bind-form-data-request-with-custom-struct">Bind form-data request with custom struct</a></li>
                <li><a href="#try-to-bind-body-into-different-structs">Try to bind body into different structs</a></li>
                <li><a href="#http2-server-push">http2 server push</a></li>
                <li><a href="#define-format-for-the-log-of-routes">Define format for the log of routes</a></li>
                <li><a href="#set-and-get-a-cookie">Set and get a cookie</a></li>
            </ul>
        </li>
        <li><a href="#testing">Testing</a></li>
        <li><a href="#users">Users</a></li>
    </ul>
    <h2><a id="user-content-installation" class="anchor" aria-hidden="true" href="#installation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Installation</h2>
    <p>To install Gin package, you need to install Go and set your Go workspace first.</p>
    <ol>
        <li>The first need <a href="https://golang.org/" rel="nofollow">Go</a> installed (<strong>version 1.10+ is required</strong>), then you can use the below Go command to install Gin.</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ go get -u github.com/gin-gonic/gin</pre></div>
    <ol start="2">
        <li>Import it in your code:</li>
    </ol>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> <span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span></pre></div>
    <ol start="3">
        <li>(Optional) Import <code>net/http</code>. This is required for example if using constants such as <code>http.StatusOK</code>.</li>
    </ol>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> <span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span></pre></div>
    <h3><a id="user-content-use-a-vendor-tool-like-govendor" class="anchor" aria-hidden="true" href="#use-a-vendor-tool-like-govendor"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Use a vendor tool like <a href="https://github.com/kardianos/govendor">Govendor</a></h3>
    <ol>
        <li><code>go get</code> govendor</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ go get github.com/kardianos/govendor</pre></div>
    <ol start="2">
        <li>Create your project folder and <code>cd</code> inside</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ mkdir -p <span class="pl-smi">$GOPATH</span>/src/github.com/myusername/project <span class="pl-k">&amp;&amp;</span> <span class="pl-c1">cd</span> <span class="pl-s"><span class="pl-pds">"</span><span class="pl-smi">$_</span><span class="pl-pds">"</span></span></pre></div>
    <p>If you are on a Mac and you're installing Go 1.8 (released: Feb 2017) or later, GOPATH is automatically determined by the Go toolchain for you. It defaults to $HOME/go on macOS so you can create your project like this</p>
    <div class="highlight highlight-source-shell"><pre>$ mkdir -p <span class="pl-smi">$HOME</span>/go/src/github.com/myusername/project <span class="pl-k">&amp;&amp;</span> <span class="pl-c1">cd</span> <span class="pl-s"><span class="pl-pds">"</span><span class="pl-smi">$_</span><span class="pl-pds">"</span></span></pre></div>
    <ol start="3">
        <li>Vendor init your project and add gin</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ govendor init
$ govendor fetch github.com/gin-gonic/gin@v1.3</pre></div>
    <ol start="4">
        <li>Copy a starting template inside your project</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ curl https://raw.githubusercontent.com/gin-gonic/examples/master/basic/main.go <span class="pl-k">&gt;</span> main.go</pre></div>
    <ol start="5">
        <li>Run your project</li>
    </ol>
    <div class="highlight highlight-source-shell"><pre>$ go run main.go</pre></div>
    <h2><a id="user-content-quick-start" class="anchor" aria-hidden="true" href="#quick-start"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Quick start</h2>
    <div class="highlight highlight-source-shell"><pre><span class="pl-c"><span class="pl-c">#</span> assume the following codes in example.go file</span>
$ cat example.go</pre></div>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> <span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>,
		})
	})
	r.<span class="pl-c1">Run</span>() <span class="pl-c"><span class="pl-c">//</span> listen and serve on 0.0.0.0:8080</span>
}</pre></div>
    <pre><code># run example.go and visit 0.0.0.0:8080/ping on browser
$ go run example.go
</code></pre>
    <h2><a id="user-content-benchmarks" class="anchor" aria-hidden="true" href="#benchmarks"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Benchmarks</h2>
    <p>Gin uses a custom version of <a href="https://github.com/julienschmidt/httprouter">HttpRouter</a></p>
    <p><a href="/gin-gonic/gin/blob/master/BENCHMARKS.md">See all benchmarks</a></p>
    <table>
        <thead>
        <tr>
            <th>Benchmark name</th>
            <th align="right">(1)</th>
            <th align="right">(2)</th>
            <th align="right">(3)</th>
            <th align="right">(4)</th>
        </tr>
        </thead>
        <tbody>
        <tr>
            <td><strong>BenchmarkGin_GithubAll</strong></td>
            <td align="right"><strong>30000</strong></td>
            <td align="right"><strong>48375</strong></td>
            <td align="right"><strong>0</strong></td>
            <td align="right"><strong>0</strong></td>
        </tr>
        <tr>
            <td>BenchmarkAce_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">134059</td>
            <td align="right">13792</td>
            <td align="right">167</td>
        </tr>
        <tr>
            <td>BenchmarkBear_GithubAll</td>
            <td align="right">5000</td>
            <td align="right">534445</td>
            <td align="right">86448</td>
            <td align="right">943</td>
        </tr>
        <tr>
            <td>BenchmarkBeego_GithubAll</td>
            <td align="right">3000</td>
            <td align="right">592444</td>
            <td align="right">74705</td>
            <td align="right">812</td>
        </tr>
        <tr>
            <td>BenchmarkBone_GithubAll</td>
            <td align="right">200</td>
            <td align="right">6957308</td>
            <td align="right">698784</td>
            <td align="right">8453</td>
        </tr>
        <tr>
            <td>BenchmarkDenco_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">158819</td>
            <td align="right">20224</td>
            <td align="right">167</td>
        </tr>
        <tr>
            <td>BenchmarkEcho_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">154700</td>
            <td align="right">6496</td>
            <td align="right">203</td>
        </tr>
        <tr>
            <td>BenchmarkGocraftWeb_GithubAll</td>
            <td align="right">3000</td>
            <td align="right">570806</td>
            <td align="right">131656</td>
            <td align="right">1686</td>
        </tr>
        <tr>
            <td>BenchmarkGoji_GithubAll</td>
            <td align="right">2000</td>
            <td align="right">818034</td>
            <td align="right">56112</td>
            <td align="right">334</td>
        </tr>
        <tr>
            <td>BenchmarkGojiv2_GithubAll</td>
            <td align="right">2000</td>
            <td align="right">1213973</td>
            <td align="right">274768</td>
            <td align="right">3712</td>
        </tr>
        <tr>
            <td>BenchmarkGoJsonRest_GithubAll</td>
            <td align="right">2000</td>
            <td align="right">785796</td>
            <td align="right">134371</td>
            <td align="right">2737</td>
        </tr>
        <tr>
            <td>BenchmarkGoRestful_GithubAll</td>
            <td align="right">300</td>
            <td align="right">5238188</td>
            <td align="right">689672</td>
            <td align="right">4519</td>
        </tr>
        <tr>
            <td>BenchmarkGorillaMux_GithubAll</td>
            <td align="right">100</td>
            <td align="right">10257726</td>
            <td align="right">211840</td>
            <td align="right">2272</td>
        </tr>
        <tr>
            <td>BenchmarkHttpRouter_GithubAll</td>
            <td align="right">20000</td>
            <td align="right">105414</td>
            <td align="right">13792</td>
            <td align="right">167</td>
        </tr>
        <tr>
            <td>BenchmarkHttpTreeMux_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">319934</td>
            <td align="right">65856</td>
            <td align="right">671</td>
        </tr>
        <tr>
            <td>BenchmarkKocha_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">209442</td>
            <td align="right">23304</td>
            <td align="right">843</td>
        </tr>
        <tr>
            <td>BenchmarkLARS_GithubAll</td>
            <td align="right">20000</td>
            <td align="right">62565</td>
            <td align="right">0</td>
            <td align="right">0</td>
        </tr>
        <tr>
            <td>BenchmarkMacaron_GithubAll</td>
            <td align="right">2000</td>
            <td align="right">1161270</td>
            <td align="right">204194</td>
            <td align="right">2000</td>
        </tr>
        <tr>
            <td>BenchmarkMartini_GithubAll</td>
            <td align="right">200</td>
            <td align="right">9991713</td>
            <td align="right">226549</td>
            <td align="right">2325</td>
        </tr>
        <tr>
            <td>BenchmarkPat_GithubAll</td>
            <td align="right">200</td>
            <td align="right">5590793</td>
            <td align="right">1499568</td>
            <td align="right">27435</td>
        </tr>
        <tr>
            <td>BenchmarkPossum_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">319768</td>
            <td align="right">84448</td>
            <td align="right">609</td>
        </tr>
        <tr>
            <td>BenchmarkR2router_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">305134</td>
            <td align="right">77328</td>
            <td align="right">979</td>
        </tr>
        <tr>
            <td>BenchmarkRivet_GithubAll</td>
            <td align="right">10000</td>
            <td align="right">132134</td>
            <td align="right">16272</td>
            <td align="right">167</td>
        </tr>
        <tr>
            <td>BenchmarkTango_GithubAll</td>
            <td align="right">3000</td>
            <td align="right">552754</td>
            <td align="right">63826</td>
            <td align="right">1618</td>
        </tr>
        <tr>
            <td>BenchmarkTigerTonic_GithubAll</td>
            <td align="right">1000</td>
            <td align="right">1439483</td>
            <td align="right">239104</td>
            <td align="right">5374</td>
        </tr>
        <tr>
            <td>BenchmarkTraffic_GithubAll</td>
            <td align="right">100</td>
            <td align="right">11383067</td>
            <td align="right">2659329</td>
            <td align="right">21848</td>
        </tr>
        <tr>
            <td>BenchmarkVulcan_GithubAll</td>
            <td align="right">5000</td>
            <td align="right">394253</td>
            <td align="right">19894</td>
            <td align="right">609</td>
        </tr>
        </tbody>
    </table>
    <ul>
        <li>(1): Total Repetitions achieved in constant time, higher means more confident result</li>
        <li>(2): Single Repetition Duration (ns/op), lower is better</li>
        <li>(3): Heap Memory (B/op), lower is better</li>
        <li>(4): Average Allocations per Repetition (allocs/op), lower is better</li>
    </ul>
    <h2><a id="user-content-gin-v1-stable" class="anchor" aria-hidden="true" href="#gin-v1-stable"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Gin v1. stable</h2>
    <ul class="contains-task-list">
        <li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Zero allocation router.</li>
        <li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Still the fastest http router and framework. From routing to writing.</li>
        <li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Complete suite of unit tests</li>
        <li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> Battle tested</li>
        <li class="task-list-item"><input type="checkbox" id="" disabled="" class="task-list-item-checkbox" checked=""> API frozen, new releases will not break your code.</li>
    </ul>
    <h2><a id="user-content-build-with-jsoniter" class="anchor" aria-hidden="true" href="#build-with-jsoniter"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Build with <a href="https://github.com/json-iterator/go">jsoniter</a></h2>
    <p>Gin uses <code>encoding/json</code> as default json package but you can change to <a href="https://github.com/json-iterator/go">jsoniter</a> by build from other tags.</p>
    <div class="highlight highlight-source-shell"><pre>$ go build -tags=jsoniter <span class="pl-c1">.</span></pre></div>
    <h2><a id="user-content-api-examples" class="anchor" aria-hidden="true" href="#api-examples"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>API Examples</h2>
    <p>You can find a number of ready-to-run examples at <a href="https://github.com/gin-gonic/examples">Gin examples repository</a>.</p>
    <h3><a id="user-content-using-get-post-put-patch-delete-and-options" class="anchor" aria-hidden="true" href="#using-get-post-put-patch-delete-and-options"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using GET, POST, PUT, PATCH, DELETE and OPTIONS</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-c"><span class="pl-c">//</span> Creates a gin router with default middleware:</span>
	<span class="pl-c"><span class="pl-c">//</span> logger and recovery (crash-free) middleware</span>
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someGet<span class="pl-pds">"</span></span>, getting)
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/somePost<span class="pl-pds">"</span></span>, posting)
	router.<span class="pl-c1">PUT</span>(<span class="pl-s"><span class="pl-pds">"</span>/somePut<span class="pl-pds">"</span></span>, putting)
	router.<span class="pl-c1">DELETE</span>(<span class="pl-s"><span class="pl-pds">"</span>/someDelete<span class="pl-pds">"</span></span>, deleting)
	router.<span class="pl-c1">PATCH</span>(<span class="pl-s"><span class="pl-pds">"</span>/somePatch<span class="pl-pds">"</span></span>, patching)
	router.<span class="pl-c1">HEAD</span>(<span class="pl-s"><span class="pl-pds">"</span>/someHead<span class="pl-pds">"</span></span>, head)
	router.<span class="pl-c1">OPTIONS</span>(<span class="pl-s"><span class="pl-pds">"</span>/someOptions<span class="pl-pds">"</span></span>, options)

	<span class="pl-c"><span class="pl-c">//</span> By default it serves on :8080 unless a</span>
	<span class="pl-c"><span class="pl-c">//</span> PORT environment variable was defined.</span>
	router.<span class="pl-c1">Run</span>()
	<span class="pl-c"><span class="pl-c">//</span> router.Run(":3000") for a hard coded port</span>
}</pre></div>
    <h3><a id="user-content-parameters-in-path" class="anchor" aria-hidden="true" href="#parameters-in-path"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Parameters in path</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> This handler will match /user/john but will not match /user/ or /user</span>
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/user/:name<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">name</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Param</span>(<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>)
		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>Hello <span class="pl-c1">%s</span><span class="pl-pds">"</span></span>, name)
	})

	<span class="pl-c"><span class="pl-c">//</span> However, this one will match /user/john/ and also /user/john/send</span>
	<span class="pl-c"><span class="pl-c">//</span> If no other routers match /user/john, it will redirect to /user/john/</span>
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/user/:name/*action<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">name</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Param</span>(<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>)
		<span class="pl-smi">action</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Param</span>(<span class="pl-s"><span class="pl-pds">"</span>action<span class="pl-pds">"</span></span>)
		<span class="pl-smi">message</span> <span class="pl-k">:=</span> name + <span class="pl-s"><span class="pl-pds">"</span> is <span class="pl-pds">"</span></span> + action
		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, message)
	})

	<span class="pl-c"><span class="pl-c">//</span> For each matched request Context will hold the route definition</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/user/:name/*action<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">FullPath</span>() == <span class="pl-s"><span class="pl-pds">"</span>/user/:name/*action<span class="pl-pds">"</span></span> <span class="pl-c"><span class="pl-c">//</span> true</span>
	})

	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-querystring-parameters" class="anchor" aria-hidden="true" href="#querystring-parameters"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Querystring parameters</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Query string parameters are parsed using the existing underlying request object.</span>
	<span class="pl-c"><span class="pl-c">//</span> The request responds to a url matching:  /welcome?firstname=Jane&amp;lastname=Doe</span>
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/welcome<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">firstname</span> <span class="pl-k">:=</span> c.<span class="pl-c1">DefaultQuery</span>(<span class="pl-s"><span class="pl-pds">"</span>firstname<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>Guest<span class="pl-pds">"</span></span>)
		<span class="pl-smi">lastname</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Query</span>(<span class="pl-s"><span class="pl-pds">"</span>lastname<span class="pl-pds">"</span></span>) <span class="pl-c"><span class="pl-c">//</span> shortcut for c.Request.URL.Query().Get("lastname")</span>

		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>Hello <span class="pl-c1">%s</span> <span class="pl-c1">%s</span><span class="pl-pds">"</span></span>, firstname, lastname)
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-multiparturlencoded-form" class="anchor" aria-hidden="true" href="#multiparturlencoded-form"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Multipart/Urlencoded Form</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/form_post<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">message</span> <span class="pl-k">:=</span> c.<span class="pl-c1">PostForm</span>(<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>)
		<span class="pl-smi">nick</span> <span class="pl-k">:=</span> c.<span class="pl-c1">DefaultPostForm</span>(<span class="pl-s"><span class="pl-pds">"</span>nick<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>anonymous<span class="pl-pds">"</span></span>)

		c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>:  <span class="pl-s"><span class="pl-pds">"</span>posted<span class="pl-pds">"</span></span>,
			<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: message,
			<span class="pl-s"><span class="pl-pds">"</span>nick<span class="pl-pds">"</span></span>:    nick,
		})
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-another-example-query--post-form" class="anchor" aria-hidden="true" href="#another-example-query--post-form"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Another example: query + post form</h3>
    <pre><code>POST /post?id=1234&amp;page=1 HTTP/1.1
Content-Type: application/x-www-form-urlencoded

name=manu&amp;message=this_is_great
</code></pre>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/post<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {

		<span class="pl-smi">id</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Query</span>(<span class="pl-s"><span class="pl-pds">"</span>id<span class="pl-pds">"</span></span>)
		<span class="pl-smi">page</span> <span class="pl-k">:=</span> c.<span class="pl-c1">DefaultQuery</span>(<span class="pl-s"><span class="pl-pds">"</span>page<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>0<span class="pl-pds">"</span></span>)
		<span class="pl-smi">name</span> <span class="pl-k">:=</span> c.<span class="pl-c1">PostForm</span>(<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>)
		<span class="pl-smi">message</span> <span class="pl-k">:=</span> c.<span class="pl-c1">PostForm</span>(<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>)

		fmt.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span>id: <span class="pl-c1">%s</span>; page: <span class="pl-c1">%s</span>; name: <span class="pl-c1">%s</span>; message: <span class="pl-c1">%s</span><span class="pl-pds">"</span></span>, id, page, name, message)
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <pre><code>id: 1234; page: 1; name: manu; message: this_is_great
</code></pre>
    <h3><a id="user-content-map-as-querystring-or-postform-parameters" class="anchor" aria-hidden="true" href="#map-as-querystring-or-postform-parameters"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Map as querystring or postform parameters</h3>
    <pre><code>POST /post?ids[a]=1234&amp;ids[b]=hello HTTP/1.1
Content-Type: application/x-www-form-urlencoded

names[first]=thinkerou&amp;names[second]=tianou
</code></pre>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/post<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {

		<span class="pl-smi">ids</span> <span class="pl-k">:=</span> c.<span class="pl-c1">QueryMap</span>(<span class="pl-s"><span class="pl-pds">"</span>ids<span class="pl-pds">"</span></span>)
		<span class="pl-smi">names</span> <span class="pl-k">:=</span> c.<span class="pl-c1">PostFormMap</span>(<span class="pl-s"><span class="pl-pds">"</span>names<span class="pl-pds">"</span></span>)

		fmt.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span>ids: <span class="pl-c1">%v</span>; names: <span class="pl-c1">%v</span><span class="pl-pds">"</span></span>, ids, names)
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <pre><code>ids: map[b:hello a:1234], names: map[second:tianou first:thinkerou]
</code></pre>
    <h3><a id="user-content-upload-files" class="anchor" aria-hidden="true" href="#upload-files"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Upload files</h3>
    <h4><a id="user-content-single-file" class="anchor" aria-hidden="true" href="#single-file"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Single file</h4>
    <p>References issue <a href="https://github.com/gin-gonic/gin/issues/774">#774</a> and detail <a href="https://github.com/gin-gonic/examples/tree/master/upload-file/single">example code</a>.</p>
    <p><code>file.Filename</code> <strong>SHOULD NOT</strong> be trusted. See <a href="https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives" rel="nofollow"><code>Content-Disposition</code> on MDN</a> and <a href="https://github.com/gin-gonic/gin/issues/1693">#1693</a></p>
    <blockquote>
        <p>The filename is always optional and must not be used blindly by the application: path information should be stripped, and conversion to the server file system rules should be done.</p>
    </blockquote>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	<span class="pl-c"><span class="pl-c">//</span> Set a lower memory limit for multipart forms (default is 32 MiB)</span>
	<span class="pl-c"><span class="pl-c">//</span> router.MaxMultipartMemory = 8 &lt;&lt; 20  // 8 MiB</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/upload<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> single file</span>
		<span class="pl-smi">file</span>, <span class="pl-smi">_</span> <span class="pl-k">:=</span> c.<span class="pl-c1">FormFile</span>(<span class="pl-s"><span class="pl-pds">"</span>file<span class="pl-pds">"</span></span>)
		log.<span class="pl-c1">Println</span>(file.<span class="pl-smi">Filename</span>)

		<span class="pl-c"><span class="pl-c">//</span> Upload the file to specific dst.</span>
		<span class="pl-c"><span class="pl-c">//</span> c.SaveUploadedFile(file, dst)</span>

		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, fmt.<span class="pl-c1">Sprintf</span>(<span class="pl-s"><span class="pl-pds">"</span>'<span class="pl-c1">%s</span>' uploaded!<span class="pl-pds">"</span></span>, file.<span class="pl-smi">Filename</span>))
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>How to <code>curl</code>:</p>
    <div class="highlight highlight-source-shell"><pre>curl -X POST http://localhost:8080/upload \
  -F <span class="pl-s"><span class="pl-pds">"</span>file=@/Users/appleboy/test.zip<span class="pl-pds">"</span></span> \
  -H <span class="pl-s"><span class="pl-pds">"</span>Content-Type: multipart/form-data<span class="pl-pds">"</span></span></pre></div>
    <h4><a id="user-content-multiple-files" class="anchor" aria-hidden="true" href="#multiple-files"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Multiple files</h4>
    <p>See the detail <a href="https://github.com/gin-gonic/examples/tree/master/upload-file/multiple">example code</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	<span class="pl-c"><span class="pl-c">//</span> Set a lower memory limit for multipart forms (default is 32 MiB)</span>
	<span class="pl-c"><span class="pl-c">//</span> router.MaxMultipartMemory = 8 &lt;&lt; 20  // 8 MiB</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/upload<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> Multipart form</span>
		<span class="pl-smi">form</span>, <span class="pl-smi">_</span> <span class="pl-k">:=</span> c.<span class="pl-c1">MultipartForm</span>()
		<span class="pl-smi">files</span> <span class="pl-k">:=</span> form.<span class="pl-smi">File</span>[<span class="pl-s"><span class="pl-pds">"</span>upload[]<span class="pl-pds">"</span></span>]

		<span class="pl-k">for</span> <span class="pl-smi">_</span>, <span class="pl-smi">file</span> <span class="pl-k">:=</span> <span class="pl-k">range</span> files {
			log.<span class="pl-c1">Println</span>(file.<span class="pl-smi">Filename</span>)

			<span class="pl-c"><span class="pl-c">//</span> Upload the file to specific dst.</span>
			<span class="pl-c"><span class="pl-c">//</span> c.SaveUploadedFile(file, dst)</span>
		}
		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, fmt.<span class="pl-c1">Sprintf</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%d</span> files uploaded!<span class="pl-pds">"</span></span>, <span class="pl-c1">len</span>(files)))
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>How to <code>curl</code>:</p>
    <div class="highlight highlight-source-shell"><pre>curl -X POST http://localhost:8080/upload \
  -F <span class="pl-s"><span class="pl-pds">"</span>upload[]=@/Users/appleboy/test1.zip<span class="pl-pds">"</span></span> \
  -F <span class="pl-s"><span class="pl-pds">"</span>upload[]=@/Users/appleboy/test2.zip<span class="pl-pds">"</span></span> \
  -H <span class="pl-s"><span class="pl-pds">"</span>Content-Type: multipart/form-data<span class="pl-pds">"</span></span></pre></div>
    <h3><a id="user-content-grouping-routes" class="anchor" aria-hidden="true" href="#grouping-routes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Grouping routes</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Simple group: v1</span>
	<span class="pl-smi">v1</span> <span class="pl-k">:=</span> router.<span class="pl-c1">Group</span>(<span class="pl-s"><span class="pl-pds">"</span>/v1<span class="pl-pds">"</span></span>)
	{
		v1.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/login<span class="pl-pds">"</span></span>, loginEndpoint)
		v1.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/submit<span class="pl-pds">"</span></span>, submitEndpoint)
		v1.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/read<span class="pl-pds">"</span></span>, readEndpoint)
	}

	<span class="pl-c"><span class="pl-c">//</span> Simple group: v2</span>
	<span class="pl-smi">v2</span> <span class="pl-k">:=</span> router.<span class="pl-c1">Group</span>(<span class="pl-s"><span class="pl-pds">"</span>/v2<span class="pl-pds">"</span></span>)
	{
		v2.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/login<span class="pl-pds">"</span></span>, loginEndpoint)
		v2.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/submit<span class="pl-pds">"</span></span>, submitEndpoint)
		v2.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/read<span class="pl-pds">"</span></span>, readEndpoint)
	}

	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-blank-gin-without-middleware-by-default" class="anchor" aria-hidden="true" href="#blank-gin-without-middleware-by-default"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Blank Gin without middleware by default</h3>
    <p>Use</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()</pre></div>
    <p>instead of</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-c"><span class="pl-c">//</span> Default With the Logger and Recovery middleware already attached</span>
<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()</pre></div>
    <h3><a id="user-content-using-middleware" class="anchor" aria-hidden="true" href="#using-middleware"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using middleware</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-c"><span class="pl-c">//</span> Creates a router without any middleware by default</span>
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()

	<span class="pl-c"><span class="pl-c">//</span> Global middleware</span>
	<span class="pl-c"><span class="pl-c">//</span> Logger middleware will write the logs to gin.DefaultWriter even if you set with GIN_MODE=release.</span>
	<span class="pl-c"><span class="pl-c">//</span> By default gin.DefaultWriter = os.Stdout</span>
	r.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">Logger</span>())

	<span class="pl-c"><span class="pl-c">//</span> Recovery middleware recovers from any panics and writes a 500 if there was one.</span>
	r.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">Recovery</span>())

	<span class="pl-c"><span class="pl-c">//</span> Per route middleware, you can add as many as you desire.</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/benchmark<span class="pl-pds">"</span></span>, <span class="pl-c1">MyBenchLogger</span>(), benchEndpoint)

	<span class="pl-c"><span class="pl-c">//</span> Authorization group</span>
	<span class="pl-c"><span class="pl-c">//</span> authorized := r.Group("/", AuthRequired())</span>
	<span class="pl-c"><span class="pl-c">//</span> exactly the same as:</span>
	<span class="pl-smi">authorized</span> <span class="pl-k">:=</span> r.<span class="pl-c1">Group</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>)
	<span class="pl-c"><span class="pl-c">//</span> per group middleware! in this case we use the custom created</span>
	<span class="pl-c"><span class="pl-c">//</span> AuthRequired() middleware just in the "authorized" group.</span>
	authorized.<span class="pl-c1">Use</span>(<span class="pl-c1">AuthRequired</span>())
	{
		authorized.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/login<span class="pl-pds">"</span></span>, loginEndpoint)
		authorized.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/submit<span class="pl-pds">"</span></span>, submitEndpoint)
		authorized.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/read<span class="pl-pds">"</span></span>, readEndpoint)

		<span class="pl-c"><span class="pl-c">//</span> nested group</span>
		<span class="pl-smi">testing</span> <span class="pl-k">:=</span> authorized.<span class="pl-c1">Group</span>(<span class="pl-s"><span class="pl-pds">"</span>testing<span class="pl-pds">"</span></span>)
		testing.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/analytics<span class="pl-pds">"</span></span>, analyticsEndpoint)
	}

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-how-to-write-log-file" class="anchor" aria-hidden="true" href="#how-to-write-log-file"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>How to write log file</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
    <span class="pl-c"><span class="pl-c">//</span> Disable Console Color, you don't need console color when writing the logs to file.</span>
    gin.<span class="pl-c1">DisableConsoleColor</span>()

    <span class="pl-c"><span class="pl-c">//</span> Logging to a file.</span>
    <span class="pl-smi">f</span>, <span class="pl-smi">_</span> <span class="pl-k">:=</span> os.<span class="pl-c1">Create</span>(<span class="pl-s"><span class="pl-pds">"</span>gin.log<span class="pl-pds">"</span></span>)
    gin.<span class="pl-smi">DefaultWriter</span> = io.<span class="pl-c1">MultiWriter</span>(f)

    <span class="pl-c"><span class="pl-c">//</span> Use the following code if you need to write the logs to file and console at the same time.</span>
    <span class="pl-c"><span class="pl-c">//</span> gin.DefaultWriter = io.MultiWriter(f, os.Stdout)</span>

    <span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
    router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
        c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
    })

 &nbsp; &nbsp;router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-custom-log-format" class="anchor" aria-hidden="true" href="#custom-log-format"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Log Format</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()

	<span class="pl-c"><span class="pl-c">//</span> LoggerWithFormatter middleware will write the logs to gin.DefaultWriter</span>
	<span class="pl-c"><span class="pl-c">//</span> By default gin.DefaultWriter = os.Stdout</span>
	router.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">LoggerWithFormatter</span>(<span class="pl-k">func</span>(param gin.<span class="pl-smi">LogFormatterParams</span>) <span class="pl-k">string</span> {

		<span class="pl-c"><span class="pl-c">//</span> your custom format</span>
		<span class="pl-k">return</span> fmt.<span class="pl-c1">Sprintf</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%s</span> - [<span class="pl-c1">%s</span>] <span class="pl-cce">\"</span><span class="pl-c1">%s</span> <span class="pl-c1">%s</span> <span class="pl-c1">%s</span> <span class="pl-c1">%d</span> <span class="pl-c1">%s</span> <span class="pl-cce">\"</span><span class="pl-c1">%s</span><span class="pl-cce">\"</span> <span class="pl-c1">%s</span><span class="pl-cce">\"\n</span><span class="pl-pds">"</span></span>,
				param.<span class="pl-smi">ClientIP</span>,
				param.<span class="pl-smi">TimeStamp</span>.<span class="pl-c1">Format</span>(time.<span class="pl-smi">RFC1123</span>),
				param.<span class="pl-smi">Method</span>,
				param.<span class="pl-smi">Path</span>,
				param.<span class="pl-smi">Request</span>.<span class="pl-smi">Proto</span>,
				param.<span class="pl-smi">StatusCode</span>,
				param.<span class="pl-smi">Latency</span>,
				param.<span class="pl-smi">Request</span>.<span class="pl-c1">UserAgent</span>(),
				param.<span class="pl-smi">ErrorMessage</span>,
		)
	}))
	router.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">Recovery</span>())

	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
	})

	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p><strong>Sample Output</strong></p>
    <pre><code>::1 - [Fri, 07 Dec 2018 17:04:38 JST] "GET /ping HTTP/1.1 200 122.767µs "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.80 Safari/537.36" "
</code></pre>
    <h3><a id="user-content-controlling-log-output-coloring" class="anchor" aria-hidden="true" href="#controlling-log-output-coloring"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Controlling Log output coloring</h3>
    <p>By default, logs output on console should be colorized depending on the detected TTY.</p>
    <p>Never colorize logs:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
    <span class="pl-c"><span class="pl-c">//</span> Disable log's color</span>
    gin.<span class="pl-c1">DisableConsoleColor</span>()

    <span class="pl-c"><span class="pl-c">//</span> Creates a gin router with default middleware:</span>
    <span class="pl-c"><span class="pl-c">//</span> logger and recovery (crash-free) middleware</span>
    <span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

    router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
        c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
    })

    router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>Always colorize logs:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
    <span class="pl-c"><span class="pl-c">//</span> Force log's color</span>
    gin.<span class="pl-c1">ForceConsoleColor</span>()

    <span class="pl-c"><span class="pl-c">//</span> Creates a gin router with default middleware:</span>
    <span class="pl-c"><span class="pl-c">//</span> logger and recovery (crash-free) middleware</span>
    <span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

    router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
        c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
    })

    router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-model-binding-and-validation" class="anchor" aria-hidden="true" href="#model-binding-and-validation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Model binding and validation</h3>
    <p>To bind a request body into a type, use model binding. We currently support binding of JSON, XML, YAML and standard form values (foo=bar&amp;boo=baz).</p>
    <p>Gin uses <a href="https://github.com/go-playground/validator"><strong>go-playground/validator.v8</strong></a> for validation. Check the full docs on tags usage <a href="http://godoc.org/gopkg.in/go-playground/validator.v8#hdr-Baked_In_Validators_and_Tags" rel="nofollow">here</a>.</p>
    <p>Note that you need to set the corresponding binding tag on all fields you want to bind. For example, when binding from JSON, set <code>json:"fieldname"</code>.</p>
    <p>Also, Gin provides two sets of methods for binding:</p>
    <ul>
        <li><strong>Type</strong> - Must bind
            <ul>
                <li><strong>Methods</strong> - <code>Bind</code>, <code>BindJSON</code>, <code>BindXML</code>, <code>BindQuery</code>, <code>BindYAML</code>, <code>BindHeader</code></li>
                <li><strong>Behavior</strong> - These methods use <code>MustBindWith</code> under the hood. If there is a binding error, the request is aborted with <code>c.AbortWithError(400, err).SetType(ErrorTypeBind)</code>. This sets the response status code to 400 and the <code>Content-Type</code> header is set to <code>text/plain; charset=utf-8</code>. Note that if you try to set the response code after this, it will result in a warning <code>[GIN-debug] [WARNING] Headers were already written. Wanted to override status code 400 with 422</code>. If you wish to have greater control over the behavior, consider using the <code>ShouldBind</code> equivalent method.</li>
            </ul>
        </li>
        <li><strong>Type</strong> - Should bind
            <ul>
                <li><strong>Methods</strong> - <code>ShouldBind</code>, <code>ShouldBindJSON</code>, <code>ShouldBindXML</code>, <code>ShouldBindQuery</code>, <code>ShouldBindYAML</code>, <code>ShouldBindHeader</code></li>
                <li><strong>Behavior</strong> - These methods use <code>ShouldBindWith</code> under the hood. If there is a binding error, the error is returned and it is the developer's responsibility to handle the request and error appropriately.</li>
            </ul>
        </li>
    </ul>
    <p>When using the Bind-method, Gin tries to infer the binder depending on the Content-Type header. If you are sure what you are binding, you can use <code>MustBindWith</code> or <code>ShouldBindWith</code>.</p>
    <p>You can also specify that specific fields are required. If a field is decorated with <code>binding:"required"</code> and has a empty value when binding, an error will be returned.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-c"><span class="pl-c">//</span> Binding from JSON</span>
<span class="pl-k">type</span> <span class="pl-v">Login</span> <span class="pl-k">struct</span> {
	<span class="pl-v">User</span>     <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"user" json:"user" xml:"user"  binding:"required"<span class="pl-pds">`</span></span>
	<span class="pl-v">Password</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"password" json:"password" xml:"password" binding:"required"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Example for binding JSON ({"user": "manu", "password": "123"})</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/loginJSON<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-k">var</span> <span class="pl-smi">json</span> Login
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindJSON</span>(&amp;json); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusBadRequest</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: err.<span class="pl-c1">Error</span>()})
			<span class="pl-k">return</span>
		}

		<span class="pl-k">if</span> json.<span class="pl-smi">User</span> != <span class="pl-s"><span class="pl-pds">"</span>manu<span class="pl-pds">"</span></span> || json.<span class="pl-smi">Password</span> != <span class="pl-s"><span class="pl-pds">"</span>123<span class="pl-pds">"</span></span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusUnauthorized</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>unauthorized<span class="pl-pds">"</span></span>})
			<span class="pl-k">return</span>
		}

		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>you are logged in<span class="pl-pds">"</span></span>})
	})

	<span class="pl-c"><span class="pl-c">//</span> Example for binding XML (</span>
	<span class="pl-c"><span class="pl-c">//</span>	&lt;?xml version="1.0" encoding="UTF-8"?&gt;</span>
	<span class="pl-c"><span class="pl-c">//</span>	&lt;root&gt;</span>
	<span class="pl-c"><span class="pl-c">//</span>		&lt;user&gt;user&lt;/user&gt;</span>
	<span class="pl-c"><span class="pl-c">//</span>		&lt;password&gt;123&lt;/password&gt;</span>
	<span class="pl-c"><span class="pl-c">//</span>	&lt;/root&gt;)</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/loginXML<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-k">var</span> <span class="pl-smi">xml</span> Login
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindXML</span>(&amp;xml); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusBadRequest</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: err.<span class="pl-c1">Error</span>()})
			<span class="pl-k">return</span>
		}

		<span class="pl-k">if</span> xml.<span class="pl-smi">User</span> != <span class="pl-s"><span class="pl-pds">"</span>manu<span class="pl-pds">"</span></span> || xml.<span class="pl-smi">Password</span> != <span class="pl-s"><span class="pl-pds">"</span>123<span class="pl-pds">"</span></span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusUnauthorized</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>unauthorized<span class="pl-pds">"</span></span>})
			<span class="pl-k">return</span>
		}

		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>you are logged in<span class="pl-pds">"</span></span>})
	})

	<span class="pl-c"><span class="pl-c">//</span> Example for binding a HTML form (user=manu&amp;password=123)</span>
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/loginForm<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-k">var</span> <span class="pl-smi">form</span> Login
		<span class="pl-c"><span class="pl-c">//</span> This will infer what binder to use depending on the content-type header.</span>
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBind</span>(&amp;form); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusBadRequest</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: err.<span class="pl-c1">Error</span>()})
			<span class="pl-k">return</span>
		}

		<span class="pl-k">if</span> form.<span class="pl-smi">User</span> != <span class="pl-s"><span class="pl-pds">"</span>manu<span class="pl-pds">"</span></span> || form.<span class="pl-smi">Password</span> != <span class="pl-s"><span class="pl-pds">"</span>123<span class="pl-pds">"</span></span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusUnauthorized</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>unauthorized<span class="pl-pds">"</span></span>})
			<span class="pl-k">return</span>
		}

		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>you are logged in<span class="pl-pds">"</span></span>})
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p><strong>Sample request</strong></p>
    <div class="highlight highlight-source-shell"><pre>$ curl -v -X POST \
  http://localhost:8080/loginJSON \
  -H <span class="pl-s"><span class="pl-pds">'</span>content-type: application/json<span class="pl-pds">'</span></span> \
  -d <span class="pl-s"><span class="pl-pds">'</span>{ "user": "manu" }<span class="pl-pds">'</span></span>
<span class="pl-k">&gt;</span> POST /loginJSON HTTP/1.1
<span class="pl-k">&gt;</span> Host: localhost:8080
<span class="pl-k">&gt;</span> User-Agent: curl/7.51.0
<span class="pl-k">&gt;</span> Accept: <span class="pl-k">*</span>/<span class="pl-k">*</span>
<span class="pl-k">&gt;</span> content-type: application/json
<span class="pl-k">&gt;</span> Content-Length: 18
<span class="pl-k">&gt;</span>
<span class="pl-k">*</span> upload completely sent off: 18 out of 18 bytes
<span class="pl-k">&lt;</span> HTTP/1.1 400 Bad Request
<span class="pl-k">&lt;</span> Content-Type: application/json<span class="pl-k">;</span> charset=utf-8
<span class="pl-k">&lt;</span> Date: Fri, 04 Aug 2017 03:51:31 GMT
<span class="pl-k">&lt;</span> Content-Length: 100
<span class="pl-k">&lt;</span>
{<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>:<span class="pl-s"><span class="pl-pds">"</span>Key: 'Login.Password' Error:Field validation for 'Password' failed on the 'required' tag<span class="pl-pds">"</span></span>}</pre></div>
    <p><strong>Skip validate</strong></p>
    <p>When running the above example using the above the <code>curl</code> command, it returns error. Because the example use <code>binding:"required"</code> for <code>Password</code>. If use <code>binding:"-"</code> for <code>Password</code>, then it will not return error when running the above example again.</p>
    <h3><a id="user-content-custom-validators" class="anchor" aria-hidden="true" href="#custom-validators"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Validators</h3>
    <p>It is also possible to register custom validators. See the <a href="https://github.com/gin-gonic/examples/tree/master/custom-validation/server.go">example code</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>reflect<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>time<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin/binding<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>gopkg.in/go-playground/validator.v8<span class="pl-pds">"</span></span>
)

<span class="pl-c"><span class="pl-c">//</span> Booking contains binded and validated data.</span>
<span class="pl-k">type</span> <span class="pl-v">Booking</span> <span class="pl-k">struct</span> {
	<span class="pl-v">CheckIn</span>  time.<span class="pl-smi">Time</span> <span class="pl-s"><span class="pl-pds">`</span>form:"check_in" binding:"required,bookabledate" time_format:"2006-01-02"<span class="pl-pds">`</span></span>
	<span class="pl-v">CheckOut</span> time.<span class="pl-smi">Time</span> <span class="pl-s"><span class="pl-pds">`</span>form:"check_out" binding:"required,gtfield=CheckIn" time_format:"2006-01-02"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-c1">bookableDate</span>(
	v *validator.<span class="pl-smi">Validate</span>, topStruct reflect.<span class="pl-smi">Value</span>, currentStructOrField reflect.<span class="pl-smi">Value</span>,
	field reflect.<span class="pl-smi">Value</span>, fieldType reflect.<span class="pl-smi">Type</span>, fieldKind reflect.<span class="pl-smi">Kind</span>, param <span class="pl-k">string</span>,
) <span class="pl-k">bool</span> {
	<span class="pl-k">if</span> <span class="pl-smi">date</span>, <span class="pl-smi">ok</span> <span class="pl-k">:=</span> field.<span class="pl-c1">Interface</span>().(time.<span class="pl-smi">Time</span>); ok {
		<span class="pl-smi">today</span> <span class="pl-k">:=</span> time.<span class="pl-c1">Now</span>()
		<span class="pl-k">if</span> today.<span class="pl-c1">After</span>(date) {
			<span class="pl-k">return</span> <span class="pl-c1">false</span>
		}
	}
	<span class="pl-k">return</span> <span class="pl-c1">true</span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">route</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-k">if</span> <span class="pl-smi">v</span>, <span class="pl-smi">ok</span> <span class="pl-k">:=</span> binding.<span class="pl-smi">Validator</span>.<span class="pl-c1">Engine</span>().(*validator.<span class="pl-smi">Validate</span>); ok {
		v.<span class="pl-c1">RegisterValidation</span>(<span class="pl-s"><span class="pl-pds">"</span>bookabledate<span class="pl-pds">"</span></span>, bookableDate)
	}

	route.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/bookable<span class="pl-pds">"</span></span>, getBookable)
	route.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8085<span class="pl-pds">"</span></span>)
}

<span class="pl-k">func</span> <span class="pl-en">getBookable</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
	<span class="pl-k">var</span> <span class="pl-smi">b</span> Booking
	<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindWith</span>(&amp;b, binding.<span class="pl-smi">Query</span>); err == <span class="pl-c1">nil</span> {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Booking dates are valid!<span class="pl-pds">"</span></span>})
	} <span class="pl-k">else</span> {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusBadRequest</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: err.<span class="pl-c1">Error</span>()})
	}
}</pre></div>
    <div class="highlight highlight-text-shell-session"><pre>$ <span class="pl-s1">curl <span class="pl-s"><span class="pl-pds">"</span>localhost:8085/bookable?check_in=2018-04-16&amp;check_out=2018-04-17<span class="pl-pds">"</span></span></span>
<span class="pl-c1">{"message":"Booking dates are valid!"}</span>

$ <span class="pl-s1">curl <span class="pl-s"><span class="pl-pds">"</span>localhost:8085/bookable?check_in=2018-03-08&amp;check_out=2018-03-09<span class="pl-pds">"</span></span></span>
<span class="pl-c1">{"error":"Key: 'Booking.CheckIn' Error:Field validation for 'CheckIn' failed on the 'bookabledate' tag"}</span></pre></div>
    <p><a href="https://github.com/go-playground/validator/releases/tag/v8.7">Struct level validations</a> can also be registered this way.
        See the <a href="https://github.com/gin-gonic/examples/tree/master/struct-lvl-validations">struct-lvl-validation example</a> to learn more.</p>
    <h3><a id="user-content-only-bind-query-string" class="anchor" aria-hidden="true" href="#only-bind-query-string"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Only Bind Query String</h3>
    <p><code>ShouldBindQuery</code> function only binds the query params and not the post data. See the <a href="https://github.com/gin-gonic/gin/issues/742#issuecomment-315953017">detail information</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">type</span> <span class="pl-v">Person</span> <span class="pl-k">struct</span> {
	<span class="pl-v">Name</span>    <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"name"<span class="pl-pds">`</span></span>
	<span class="pl-v">Address</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"address"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">route</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	route.<span class="pl-c1">Any</span>(<span class="pl-s"><span class="pl-pds">"</span>/testing<span class="pl-pds">"</span></span>, startPage)
	route.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8085<span class="pl-pds">"</span></span>)
}

<span class="pl-k">func</span> <span class="pl-en">startPage</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
	<span class="pl-k">var</span> <span class="pl-smi">person</span> Person
	<span class="pl-k">if</span> c.<span class="pl-c1">ShouldBindQuery</span>(&amp;person) == <span class="pl-c1">nil</span> {
		log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>====== Only Bind By Query String ======<span class="pl-pds">"</span></span>)
		log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">Name</span>)
		log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">Address</span>)
	}
	c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>Success<span class="pl-pds">"</span></span>)
}
</pre></div>
    <h3><a id="user-content-bind-query-string-or-post-data" class="anchor" aria-hidden="true" href="#bind-query-string-or-post-data"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bind Query String or Post Data</h3>
    <p>See the <a href="https://github.com/gin-gonic/gin/issues/742#issuecomment-264681292">detail information</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>time<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">type</span> <span class="pl-v">Person</span> <span class="pl-k">struct</span> {
        <span class="pl-v">Name</span>       <span class="pl-k">string</span>    <span class="pl-s"><span class="pl-pds">`</span>form:"name"<span class="pl-pds">`</span></span>
        <span class="pl-v">Address</span>    <span class="pl-k">string</span>    <span class="pl-s"><span class="pl-pds">`</span>form:"address"<span class="pl-pds">`</span></span>
        <span class="pl-v">Birthday</span>   time.<span class="pl-smi">Time</span> <span class="pl-s"><span class="pl-pds">`</span>form:"birthday" time_format:"2006-01-02" time_utc:"1"<span class="pl-pds">`</span></span>
        <span class="pl-v">CreateTime</span> time.<span class="pl-smi">Time</span> <span class="pl-s"><span class="pl-pds">`</span>form:"createTime" time_format:"unixNano"<span class="pl-pds">`</span></span>
        <span class="pl-v">UnixTime</span>   time.<span class="pl-smi">Time</span> <span class="pl-s"><span class="pl-pds">`</span>form:"unixTime" time_format:"unix"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">route</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	route.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/testing<span class="pl-pds">"</span></span>, startPage)
	route.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8085<span class="pl-pds">"</span></span>)
}

<span class="pl-k">func</span> <span class="pl-en">startPage</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
	<span class="pl-k">var</span> <span class="pl-smi">person</span> Person
	<span class="pl-c"><span class="pl-c">//</span> If `GET`, only `Form` binding engine (`query`) used.</span>
	<span class="pl-c"><span class="pl-c">//</span> If `POST`, first checks the `content-type` for `JSON` or `XML`, then uses `Form` (`form-data`).</span>
	<span class="pl-c"><span class="pl-c">//</span> See more at https://github.com/gin-gonic/gin/blob/master/binding/binding.go#L48</span>
        <span class="pl-k">if</span> c.<span class="pl-c1">ShouldBind</span>(&amp;person) == <span class="pl-c1">nil</span> {
                log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">Name</span>)
                log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">Address</span>)
                log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">Birthday</span>)
                log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">CreateTime</span>)
                log.<span class="pl-c1">Println</span>(person.<span class="pl-smi">UnixTime</span>)
        }

	c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>Success<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>Test it with:</p>
    <div class="highlight highlight-source-shell"><pre>$ curl -X GET <span class="pl-s"><span class="pl-pds">"</span>localhost:8085/testing?name=appleboy&amp;address=xyz&amp;birthday=1992-03-15&amp;createTime=1562400033000000123&amp;unixTime=1562400033<span class="pl-pds">"</span></span></pre></div>
    <h3><a id="user-content-bind-uri" class="anchor" aria-hidden="true" href="#bind-uri"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bind Uri</h3>
    <p>See the <a href="https://github.com/gin-gonic/gin/issues/846">detail information</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> <span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>

<span class="pl-k">type</span> <span class="pl-v">Person</span> <span class="pl-k">struct</span> {
	<span class="pl-v">ID</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>uri:"id" binding:"required,uuid"<span class="pl-pds">`</span></span>
	<span class="pl-v">Name</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>uri:"name" binding:"required"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">route</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	route.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/:name/:id<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-k">var</span> <span class="pl-smi">person</span> Person
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindUri</span>(&amp;person); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">JSON</span>(<span class="pl-c1">400</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>msg<span class="pl-pds">"</span></span>: err})
			<span class="pl-k">return</span>
		}
		c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>name<span class="pl-pds">"</span></span>: person.<span class="pl-smi">Name</span>, <span class="pl-s"><span class="pl-pds">"</span>uuid<span class="pl-pds">"</span></span>: person.<span class="pl-smi">ID</span>})
	})
	route.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8088<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>Test it with:</p>
    <div class="highlight highlight-source-shell"><pre>$ curl -v localhost:8088/thinkerou/987fbc97-4bed-5078-9f07-9141ba07c9f3
$ curl -v localhost:8088/thinkerou/not-uuid</pre></div>
    <h3><a id="user-content-bind-header" class="anchor" aria-hidden="true" href="#bind-header"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bind Header</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>fmt<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">type</span> testHeader <span class="pl-k">struct</span> {
	<span class="pl-v">Rate</span>   <span class="pl-k">int</span>    <span class="pl-s"><span class="pl-pds">`</span>header:"Rate"<span class="pl-pds">`</span></span>
	<span class="pl-v">Domain</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>header:"Domain"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">h</span> <span class="pl-k">:=</span> testHeader{}

		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindHeader</span>(&amp;h); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, err)
		}

		fmt.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%#v</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, h)
		c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>Rate<span class="pl-pds">"</span></span>: h.<span class="pl-smi">Rate</span>, <span class="pl-s"><span class="pl-pds">"</span>Domain<span class="pl-pds">"</span></span>: h.<span class="pl-smi">Domain</span>})
	})

	r.<span class="pl-c1">Run</span>()

<span class="pl-c"><span class="pl-c">//</span> client</span>
<span class="pl-c"><span class="pl-c">//</span> curl -H "rate:300" -H "domain:music" 127.0.0.1:8080/</span>
<span class="pl-c"><span class="pl-c">//</span> output</span>
<span class="pl-c"><span class="pl-c">//</span> {"Domain":"music","Rate":300}</span>
}</pre></div>
    <h3><a id="user-content-bind-html-checkboxes" class="anchor" aria-hidden="true" href="#bind-html-checkboxes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bind HTML checkboxes</h3>
    <p>See the <a href="https://github.com/gin-gonic/gin/issues/129#issuecomment-124260092">detail information</a></p>
    <p>main.go</p>
    <div class="highlight highlight-source-go"><pre>...

<span class="pl-k">type</span> myForm <span class="pl-k">struct</span> {
    <span class="pl-v">Colors</span> []<span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"colors[]"<span class="pl-pds">`</span></span>
}

...

<span class="pl-k">func</span> <span class="pl-en">formHandler</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
    <span class="pl-k">var</span> <span class="pl-smi">fakeForm</span> myForm
    c.<span class="pl-c1">ShouldBind</span>(&amp;fakeForm)
    c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>color<span class="pl-pds">"</span></span>: fakeForm.<span class="pl-smi">Colors</span>})
}

...
</pre></div>
    <p>form.html</p>
    <div class="highlight highlight-text-html-basic"><pre>&lt;<span class="pl-ent">form</span> <span class="pl-e">action</span>=<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span> <span class="pl-e">method</span>=<span class="pl-s"><span class="pl-pds">"</span>POST<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">p</span>&gt;Check some colors&lt;/<span class="pl-ent">p</span>&gt;
    &lt;<span class="pl-ent">label</span> <span class="pl-e">for</span>=<span class="pl-s"><span class="pl-pds">"</span>red<span class="pl-pds">"</span></span>&gt;Red&lt;/<span class="pl-ent">label</span>&gt;
    &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>checkbox<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>colors[]<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>red<span class="pl-pds">"</span></span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>red<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">label</span> <span class="pl-e">for</span>=<span class="pl-s"><span class="pl-pds">"</span>green<span class="pl-pds">"</span></span>&gt;Green&lt;/<span class="pl-ent">label</span>&gt;
    &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>checkbox<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>colors[]<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>green<span class="pl-pds">"</span></span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>green<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">label</span> <span class="pl-e">for</span>=<span class="pl-s"><span class="pl-pds">"</span>blue<span class="pl-pds">"</span></span>&gt;Blue&lt;/<span class="pl-ent">label</span>&gt;
    &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>checkbox<span class="pl-pds">"</span></span> <span class="pl-e">name</span>=<span class="pl-s"><span class="pl-pds">"</span>colors[]<span class="pl-pds">"</span></span> <span class="pl-e">value</span>=<span class="pl-s"><span class="pl-pds">"</span>blue<span class="pl-pds">"</span></span> <span class="pl-e">id</span>=<span class="pl-s"><span class="pl-pds">"</span>blue<span class="pl-pds">"</span></span>&gt;
    &lt;<span class="pl-ent">input</span> <span class="pl-e">type</span>=<span class="pl-s"><span class="pl-pds">"</span>submit<span class="pl-pds">"</span></span>&gt;
&lt;/<span class="pl-ent">form</span>&gt;</pre></div>
    <p>result:</p>
    <pre><code>{"color":["red","green","blue"]}
</code></pre>
    <h3><a id="user-content-multiparturlencoded-binding" class="anchor" aria-hidden="true" href="#multiparturlencoded-binding"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Multipart/Urlencoded binding</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">type</span> <span class="pl-v">ProfileForm</span> <span class="pl-k">struct</span> {
	<span class="pl-v">Name</span>   <span class="pl-k">string</span>                <span class="pl-s"><span class="pl-pds">`</span>form:"name" binding:"required"<span class="pl-pds">`</span></span>
	<span class="pl-v">Avatar</span> *multipart.<span class="pl-smi">FileHeader</span> <span class="pl-s"><span class="pl-pds">`</span>form:"avatar" binding:"required"<span class="pl-pds">`</span></span>

	<span class="pl-c"><span class="pl-c">//</span> or for multiple files</span>
	<span class="pl-c"><span class="pl-c">//</span> Avatars []*multipart.FileHeader `form:"avatar" binding:"required"`</span>
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/profile<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> you can bind multipart form with explicit binding declaration:</span>
		<span class="pl-c"><span class="pl-c">//</span> c.ShouldBindWith(&amp;form, binding.Form)</span>
		<span class="pl-c"><span class="pl-c">//</span> or you can simply use autobinding with ShouldBind method:</span>
		<span class="pl-k">var</span> <span class="pl-smi">form</span> ProfileForm
		<span class="pl-c"><span class="pl-c">//</span> in this case proper binding will be automatically selected</span>
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBind</span>(&amp;form); err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusBadRequest</span>, <span class="pl-s"><span class="pl-pds">"</span>bad request<span class="pl-pds">"</span></span>)
			<span class="pl-k">return</span>
		}

		<span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">SaveUploadedFile</span>(form.<span class="pl-smi">Avatar</span>, form.<span class="pl-smi">Avatar</span>.<span class="pl-smi">Filename</span>)
		<span class="pl-k">if</span> err != <span class="pl-c1">nil</span> {
			c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusInternalServerError</span>, <span class="pl-s"><span class="pl-pds">"</span>unknown error<span class="pl-pds">"</span></span>)
			<span class="pl-k">return</span>
		}

		<span class="pl-c"><span class="pl-c">//</span> db.Save(&amp;form)</span>

		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>ok<span class="pl-pds">"</span></span>)
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>Test it with:</p>
    <div class="highlight highlight-source-shell"><pre>$ curl -X POST -v --form name=user --form <span class="pl-s"><span class="pl-pds">"</span>avatar=@./avatar.png<span class="pl-pds">"</span></span> http://localhost:8080/profile</pre></div>
    <h3><a id="user-content-xml-json-yaml-and-protobuf-rendering" class="anchor" aria-hidden="true" href="#xml-json-yaml-and-protobuf-rendering"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>XML, JSON, YAML and ProtoBuf rendering</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> gin.H is a shortcut for map[string]interface{}</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someJSON<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>hey<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: http.<span class="pl-smi">StatusOK</span>})
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/moreJSON<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> You also can use a struct</span>
		<span class="pl-k">var</span> <span class="pl-smi">msg</span> <span class="pl-k">struct</span> {
			Name    <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>json:"user"<span class="pl-pds">`</span></span>
			Message <span class="pl-k">string</span>
			Number  <span class="pl-k">int</span>
		}
		msg.<span class="pl-smi">Name</span> = <span class="pl-s"><span class="pl-pds">"</span>Lena<span class="pl-pds">"</span></span>
		msg.<span class="pl-smi">Message</span> = <span class="pl-s"><span class="pl-pds">"</span>hey<span class="pl-pds">"</span></span>
		msg.<span class="pl-smi">Number</span> = <span class="pl-c1">123</span>
		<span class="pl-c"><span class="pl-c">//</span> Note that msg.Name becomes "user" in the JSON</span>
		<span class="pl-c"><span class="pl-c">//</span> Will output  :   {"user": "Lena", "Message": "hey", "Number": 123}</span>
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, msg)
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someXML<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">XML</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>hey<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: http.<span class="pl-smi">StatusOK</span>})
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someYAML<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">YAML</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>message<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>hey<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: http.<span class="pl-smi">StatusOK</span>})
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someProtoBuf<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">reps</span> <span class="pl-k">:=</span> []<span class="pl-k">int64</span>{<span class="pl-k">int64</span>(<span class="pl-c1">1</span>), <span class="pl-c1">int64</span>(<span class="pl-c1">2</span>)}
		<span class="pl-smi">label</span> <span class="pl-k">:=</span> <span class="pl-s"><span class="pl-pds">"</span>test<span class="pl-pds">"</span></span>
		<span class="pl-c"><span class="pl-c">//</span> The specific definition of protobuf is written in the testdata/protoexample file.</span>
		<span class="pl-smi">data</span> <span class="pl-k">:=</span> &amp;protoexample.<span class="pl-smi">Test</span>{
			Label: &amp;label,
			Reps:  reps,
		}
		<span class="pl-c"><span class="pl-c">//</span> Note that data becomes binary data in the response</span>
		<span class="pl-c"><span class="pl-c">//</span> Will output protoexample.Test protobuf serialized data</span>
		c.<span class="pl-c1">ProtoBuf</span>(http.<span class="pl-smi">StatusOK</span>, data)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h4><a id="user-content-securejson" class="anchor" aria-hidden="true" href="#securejson"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>SecureJSON</h4>
    <p>Using SecureJSON to prevent json hijacking. Default prepends <code>"while(1),"</code> to response body if the given struct is array values.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> You can also use your own secure json prefix</span>
	<span class="pl-c"><span class="pl-c">//</span> r.SecureJsonPrefix(")]}',\n")</span>

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someJSON<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">names</span> <span class="pl-k">:=</span> []<span class="pl-k">string</span>{<span class="pl-s"><span class="pl-pds">"</span>lena<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>austin<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>}

		<span class="pl-c"><span class="pl-c">//</span> Will output  :   while(1);["lena","austin","foo"]</span>
		c.<span class="pl-c1">SecureJSON</span>(http.<span class="pl-smi">StatusOK</span>, names)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h4><a id="user-content-jsonp" class="anchor" aria-hidden="true" href="#jsonp"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>JSONP</h4>
    <p>Using JSONP to request data from a server  in a different domain. Add callback to response body if the query parameter callback exists.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/JSONP<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">data</span> <span class="pl-k">:=</span> gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>,
		}

		<span class="pl-c"><span class="pl-c">//</span>callback is x</span>
		<span class="pl-c"><span class="pl-c">//</span> Will output  :   x({\"foo\":\"bar\"})</span>
		c.<span class="pl-c1">JSONP</span>(http.<span class="pl-smi">StatusOK</span>, data)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)

        <span class="pl-c"><span class="pl-c">//</span> client</span>
        <span class="pl-c"><span class="pl-c">//</span> curl http://127.0.0.1:8080/JSONP?callback=x</span>
}</pre></div>
    <h4><a id="user-content-asciijson" class="anchor" aria-hidden="true" href="#asciijson"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>AsciiJSON</h4>
    <p>Using AsciiJSON to Generates ASCII-only JSON with escaped non-ASCII chracters.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someJSON<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">data</span> <span class="pl-k">:=</span> gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>lang<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>GO语言<span class="pl-pds">"</span></span>,
			<span class="pl-s"><span class="pl-pds">"</span>tag<span class="pl-pds">"</span></span>:  <span class="pl-s"><span class="pl-pds">"</span>&lt;br&gt;<span class="pl-pds">"</span></span>,
		}

		<span class="pl-c"><span class="pl-c">//</span> will output : {"lang":"GO\u8bed\u8a00","tag":"\u003cbr\u003e"}</span>
		c.<span class="pl-c1">AsciiJSON</span>(http.<span class="pl-smi">StatusOK</span>, data)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h4><a id="user-content-purejson" class="anchor" aria-hidden="true" href="#purejson"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>PureJSON</h4>
    <p>Normally, JSON replaces special HTML characters with their unicode entities, e.g. <code>&lt;</code> becomes  <code>\u003c</code>. If you want to encode such characters literally, you can use PureJSON instead.
        This feature is unavailable in Go 1.6 and lower.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Serves unicode entities</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/json<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>html<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>&lt;b&gt;Hello, world!&lt;/b&gt;<span class="pl-pds">"</span></span>,
		})
	})

	<span class="pl-c"><span class="pl-c">//</span> Serves literal characters</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/purejson<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">PureJSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>html<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>&lt;b&gt;Hello, world!&lt;/b&gt;<span class="pl-pds">"</span></span>,
		})
	})

	<span class="pl-c"><span class="pl-c">//</span> listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-serving-static-files" class="anchor" aria-hidden="true" href="#serving-static-files"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Serving static files</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">Static</span>(<span class="pl-s"><span class="pl-pds">"</span>/assets<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>./assets<span class="pl-pds">"</span></span>)
	router.<span class="pl-c1">StaticFS</span>(<span class="pl-s"><span class="pl-pds">"</span>/more_static<span class="pl-pds">"</span></span>, http.<span class="pl-c1">Dir</span>(<span class="pl-s"><span class="pl-pds">"</span>my_file_system<span class="pl-pds">"</span></span>))
	router.<span class="pl-c1">StaticFile</span>(<span class="pl-s"><span class="pl-pds">"</span>/favicon.ico<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>./resources/favicon.ico<span class="pl-pds">"</span></span>)

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-serving-data-from-reader" class="anchor" aria-hidden="true" href="#serving-data-from-reader"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Serving data from reader</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/someDataFromReader<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">response</span>, <span class="pl-smi">err</span> <span class="pl-k">:=</span> http.<span class="pl-c1">Get</span>(<span class="pl-s"><span class="pl-pds">"</span>https://raw.githubusercontent.com/gin-gonic/logo/master/color.png<span class="pl-pds">"</span></span>)
		<span class="pl-k">if</span> err != <span class="pl-c1">nil</span> || response.<span class="pl-smi">StatusCode</span> != http.<span class="pl-smi">StatusOK</span> {
			c.<span class="pl-c1">Status</span>(http.<span class="pl-smi">StatusServiceUnavailable</span>)
			<span class="pl-k">return</span>
		}

		<span class="pl-smi">reader</span> <span class="pl-k">:=</span> response.<span class="pl-smi">Body</span>
		<span class="pl-smi">contentLength</span> <span class="pl-k">:=</span> response.<span class="pl-smi">ContentLength</span>
		<span class="pl-smi">contentType</span> <span class="pl-k">:=</span> response.<span class="pl-smi">Header</span>.<span class="pl-c1">Get</span>(<span class="pl-s"><span class="pl-pds">"</span>Content-Type<span class="pl-pds">"</span></span>)

		<span class="pl-smi">extraHeaders</span> <span class="pl-k">:=</span> <span class="pl-k">map</span>[<span class="pl-k">string</span>]<span class="pl-k">string</span>{
			<span class="pl-s"><span class="pl-pds">"</span>Content-Disposition<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">`</span>attachment; filename="gopher.png"<span class="pl-pds">`</span></span>,
		}

		c.<span class="pl-c1">DataFromReader</span>(http.<span class="pl-smi">StatusOK</span>, contentLength, contentType, reader, extraHeaders)
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-html-rendering" class="anchor" aria-hidden="true" href="#html-rendering"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>HTML rendering</h3>
    <p>Using LoadHTMLGlob() or LoadHTMLFiles()</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">LoadHTMLGlob</span>(<span class="pl-s"><span class="pl-pds">"</span>templates/*<span class="pl-pds">"</span></span>)
	<span class="pl-c"><span class="pl-c">//</span>router.LoadHTMLFiles("templates/template1.html", "templates/template2.html")</span>
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/index<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">HTML</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>index.tmpl<span class="pl-pds">"</span></span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Main website<span class="pl-pds">"</span></span>,
		})
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>templates/index.tmpl</p>
    <div class="highlight highlight-text-html-basic"><pre>&lt;<span class="pl-ent">html</span>&gt;
	&lt;<span class="pl-ent">h1</span>&gt;
		{{ .title }}
	&lt;/<span class="pl-ent">h1</span>&gt;
&lt;/<span class="pl-ent">html</span>&gt;</pre></div>
    <p>Using templates with same name in different directories</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">LoadHTMLGlob</span>(<span class="pl-s"><span class="pl-pds">"</span>templates/**/*<span class="pl-pds">"</span></span>)
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/posts/index<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">HTML</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>posts/index.tmpl<span class="pl-pds">"</span></span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Posts<span class="pl-pds">"</span></span>,
		})
	})
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/users/index<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">HTML</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>users/index.tmpl<span class="pl-pds">"</span></span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>title<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Users<span class="pl-pds">"</span></span>,
		})
	})
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>templates/posts/index.tmpl</p>
    <div class="highlight highlight-text-html-basic"><pre>{{ define "posts/index.tmpl" }}
                &lt;<span class="pl-ent">html</span>&gt;&lt;<span class="pl-ent">h1</span>&gt;
	{{ .title }}
&lt;/<span class="pl-ent">h1</span>&gt;
&lt;<span class="pl-ent">p</span>&gt;Using posts/index.tmpl&lt;/<span class="pl-ent">p</span>&gt;
&lt;/<span class="pl-ent">html</span>&gt;
{{ end }}</pre></div>
    <p>templates/users/index.tmpl</p>
    <div class="highlight highlight-text-html-basic"><pre>{{ define "users/index.tmpl" }}
                &lt;<span class="pl-ent">html</span>&gt;&lt;<span class="pl-ent">h1</span>&gt;
	{{ .title }}
&lt;/<span class="pl-ent">h1</span>&gt;
&lt;<span class="pl-ent">p</span>&gt;Using users/index.tmpl&lt;/<span class="pl-ent">p</span>&gt;
&lt;/<span class="pl-ent">html</span>&gt;
{{ end }}</pre></div>
    <h4><a id="user-content-custom-template-renderer" class="anchor" aria-hidden="true" href="#custom-template-renderer"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Template renderer</h4>
    <p>You can also use your own html template render</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> <span class="pl-s"><span class="pl-pds">"</span>html/template<span class="pl-pds">"</span></span>

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	<span class="pl-smi">html</span> <span class="pl-k">:=</span> template.<span class="pl-c1">Must</span>(template.<span class="pl-c1">ParseFiles</span>(<span class="pl-s"><span class="pl-pds">"</span>file1<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>file2<span class="pl-pds">"</span></span>))
	router.<span class="pl-c1">SetHTMLTemplate</span>(html)
	router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h4><a id="user-content-custom-delimiters" class="anchor" aria-hidden="true" href="#custom-delimiters"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Delimiters</h4>
    <p>You may use custom delims</p>
    <div class="highlight highlight-source-go"><pre>	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	r.<span class="pl-c1">Delims</span>(<span class="pl-s"><span class="pl-pds">"</span>{[{<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>}]}<span class="pl-pds">"</span></span>)
	r.<span class="pl-c1">LoadHTMLGlob</span>(<span class="pl-s"><span class="pl-pds">"</span>/path/to/templates<span class="pl-pds">"</span></span>)</pre></div>
    <h4><a id="user-content-custom-template-funcs" class="anchor" aria-hidden="true" href="#custom-template-funcs"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Template Funcs</h4>
    <p>See the detail <a href="https://github.com/gin-gonic/examples/tree/master/template">example code</a>.</p>
    <p>main.go</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> (
    <span class="pl-s"><span class="pl-pds">"</span>fmt<span class="pl-pds">"</span></span>
    <span class="pl-s"><span class="pl-pds">"</span>html/template<span class="pl-pds">"</span></span>
    <span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>
    <span class="pl-s"><span class="pl-pds">"</span>time<span class="pl-pds">"</span></span>

    <span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">formatAsDate</span>(<span class="pl-v">t</span> <span class="pl-v">time</span>.<span class="pl-v">Time</span>) <span class="pl-v">string</span> {
    <span class="pl-smi">year</span>, <span class="pl-smi">month</span>, <span class="pl-smi">day</span> <span class="pl-k">:=</span> t.<span class="pl-c1">Date</span>()
    <span class="pl-k">return</span> fmt.<span class="pl-c1">Sprintf</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-c1">%d%02d</span>/<span class="pl-c1">%02d</span><span class="pl-pds">"</span></span>, year, month, day)
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
    <span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
    router.<span class="pl-c1">Delims</span>(<span class="pl-s"><span class="pl-pds">"</span>{[{<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>}]}<span class="pl-pds">"</span></span>)
    router.<span class="pl-c1">SetFuncMap</span>(template.<span class="pl-smi">FuncMap</span>{
        <span class="pl-s"><span class="pl-pds">"</span>formatAsDate<span class="pl-pds">"</span></span>: formatAsDate,
    })
    router.<span class="pl-c1">LoadHTMLFiles</span>(<span class="pl-s"><span class="pl-pds">"</span>./testdata/template/raw.tmpl<span class="pl-pds">"</span></span>)

    router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/raw<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
        c.<span class="pl-c1">HTML</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>raw.tmpl<span class="pl-pds">"</span></span>, gin.<span class="pl-smi">H</span>{
            <span class="pl-s"><span class="pl-pds">"</span>now<span class="pl-pds">"</span></span>: time.<span class="pl-c1">Date</span>(<span class="pl-c1">2017</span>, <span class="pl-c1">07</span>, <span class="pl-c1">01</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>, <span class="pl-c1">0</span>, time.<span class="pl-smi">UTC</span>),
        })
    })

    router.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}
</pre></div>
    <p>raw.tmpl</p>
    <div class="highlight highlight-text-html-basic"><pre>Date: {[{.now | formatAsDate}]}</pre></div>
    <p>Result:</p>
    <pre><code>Date: 2017/07/01
</code></pre>
    <h3><a id="user-content-multitemplate" class="anchor" aria-hidden="true" href="#multitemplate"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Multitemplate</h3>
    <p>Gin allow by default use only one html.Template. Check <a href="https://github.com/gin-contrib/multitemplate">a multitemplate render</a> for using features like go 1.6 <code>block template</code>.</p>
    <h3><a id="user-content-redirects" class="anchor" aria-hidden="true" href="#redirects"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Redirects</h3>
    <p>Issuing a HTTP redirect is easy. Both internal and external locations are supported.</p>
    <div class="highlight highlight-source-go"><pre>r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/test<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
	c.<span class="pl-c1">Redirect</span>(http.<span class="pl-smi">StatusMovedPermanently</span>, <span class="pl-s"><span class="pl-pds">"</span>http://www.google.com/<span class="pl-pds">"</span></span>)
})</pre></div>
    <p>Issuing a Router redirect, use <code>HandleContext</code> like below.</p>
    <div class="highlight highlight-source-go"><pre>r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/test<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
    c.<span class="pl-smi">Request</span>.<span class="pl-smi">URL</span>.<span class="pl-smi">Path</span> = <span class="pl-s"><span class="pl-pds">"</span>/test2<span class="pl-pds">"</span></span>
    r.<span class="pl-c1">HandleContext</span>(c)
})
r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/test2<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
    c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>hello<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>world<span class="pl-pds">"</span></span>})
})</pre></div>
    <h3><a id="user-content-custom-middleware" class="anchor" aria-hidden="true" href="#custom-middleware"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom Middleware</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">Logger</span>() <span class="pl-v">gin</span>.<span class="pl-v">HandlerFunc</span> {
	<span class="pl-k">return</span> <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">t</span> <span class="pl-k">:=</span> time.<span class="pl-c1">Now</span>()

		<span class="pl-c"><span class="pl-c">//</span> Set example variable</span>
		c.<span class="pl-c1">Set</span>(<span class="pl-s"><span class="pl-pds">"</span>example<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>12345<span class="pl-pds">"</span></span>)

		<span class="pl-c"><span class="pl-c">//</span> before request</span>

		c.<span class="pl-c1">Next</span>()

		<span class="pl-c"><span class="pl-c">//</span> after request</span>
		<span class="pl-smi">latency</span> <span class="pl-k">:=</span> time.<span class="pl-c1">Since</span>(t)
		log.<span class="pl-c1">Print</span>(latency)

		<span class="pl-c"><span class="pl-c">//</span> access the status we are sending</span>
		<span class="pl-smi">status</span> <span class="pl-k">:=</span> c.<span class="pl-smi">Writer</span>.<span class="pl-c1">Status</span>()
		log.<span class="pl-c1">Println</span>(status)
	}
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()
	r.<span class="pl-c1">Use</span>(<span class="pl-c1">Logger</span>())

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/test<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-smi">example</span> <span class="pl-k">:=</span> c.<span class="pl-c1">MustGet</span>(<span class="pl-s"><span class="pl-pds">"</span>example<span class="pl-pds">"</span></span>).(<span class="pl-k">string</span>)

		<span class="pl-c"><span class="pl-c">//</span> it would print: "12345"</span>
		log.<span class="pl-c1">Println</span>(example)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-using-basicauth-middleware" class="anchor" aria-hidden="true" href="#using-basicauth-middleware"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Using BasicAuth() middleware</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-c"><span class="pl-c">//</span> simulate some private data</span>
<span class="pl-k">var</span> <span class="pl-smi">secrets</span> = gin.<span class="pl-smi">H</span>{
	<span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>:    gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>email<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>foo@bar.com<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>phone<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>123433<span class="pl-pds">"</span></span>},
	<span class="pl-s"><span class="pl-pds">"</span>austin<span class="pl-pds">"</span></span>: gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>email<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>austin@example.com<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>phone<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>666<span class="pl-pds">"</span></span>},
	<span class="pl-s"><span class="pl-pds">"</span>lena<span class="pl-pds">"</span></span>:   gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>email<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>lena@guapa.com<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>phone<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>523443<span class="pl-pds">"</span></span>},
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Group using gin.BasicAuth() middleware</span>
	<span class="pl-c"><span class="pl-c">//</span> gin.Accounts is a shortcut for map[string]string</span>
	<span class="pl-smi">authorized</span> <span class="pl-k">:=</span> r.<span class="pl-c1">Group</span>(<span class="pl-s"><span class="pl-pds">"</span>/admin<span class="pl-pds">"</span></span>, gin.<span class="pl-c1">BasicAuth</span>(gin.<span class="pl-smi">Accounts</span>{
		<span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>:    <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>,
		<span class="pl-s"><span class="pl-pds">"</span>austin<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>1234<span class="pl-pds">"</span></span>,
		<span class="pl-s"><span class="pl-pds">"</span>lena<span class="pl-pds">"</span></span>:   <span class="pl-s"><span class="pl-pds">"</span>hello2<span class="pl-pds">"</span></span>,
		<span class="pl-s"><span class="pl-pds">"</span>manu<span class="pl-pds">"</span></span>:   <span class="pl-s"><span class="pl-pds">"</span>4321<span class="pl-pds">"</span></span>,
	}))

	<span class="pl-c"><span class="pl-c">//</span> /admin/secrets endpoint</span>
	<span class="pl-c"><span class="pl-c">//</span> hit "localhost:8080/admin/secrets</span>
	authorized.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/secrets<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> get user, it was set by the BasicAuth middleware</span>
		<span class="pl-smi">user</span> <span class="pl-k">:=</span> c.<span class="pl-c1">MustGet</span>(gin.<span class="pl-smi">AuthUserKey</span>).(<span class="pl-k">string</span>)
		<span class="pl-k">if</span> <span class="pl-smi">secret</span>, <span class="pl-smi">ok</span> <span class="pl-k">:=</span> secrets[user]; ok {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>user<span class="pl-pds">"</span></span>: user, <span class="pl-s"><span class="pl-pds">"</span>secret<span class="pl-pds">"</span></span>: secret})
		} <span class="pl-k">else</span> {
			c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, gin.<span class="pl-smi">H</span>{<span class="pl-s"><span class="pl-pds">"</span>user<span class="pl-pds">"</span></span>: user, <span class="pl-s"><span class="pl-pds">"</span>secret<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>NO SECRET :(<span class="pl-pds">"</span></span>})
		}
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-goroutines-inside-a-middleware" class="anchor" aria-hidden="true" href="#goroutines-inside-a-middleware"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Goroutines inside a middleware</h3>
    <p>When starting new Goroutines inside a middleware or handler, you <strong>SHOULD NOT</strong> use the original context inside it, you have to use a read-only copy.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/long_async<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> create copy to be used inside the goroutine</span>
		<span class="pl-smi">cCp</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Copy</span>()
		<span class="pl-k">go</span> <span class="pl-k">func</span>() {
			<span class="pl-c"><span class="pl-c">//</span> simulate a long task with time.Sleep(). 5 seconds</span>
			time.<span class="pl-c1">Sleep</span>(<span class="pl-c1">5</span> * time.<span class="pl-smi">Second</span>)

			<span class="pl-c"><span class="pl-c">//</span> note that you are using the copied context "cCp", IMPORTANT</span>
			log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>Done! in path <span class="pl-pds">"</span></span> + cCp.<span class="pl-smi">Request</span>.<span class="pl-smi">URL</span>.<span class="pl-smi">Path</span>)
		}()
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/long_sync<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-c"><span class="pl-c">//</span> simulate a long task with time.Sleep(). 5 seconds</span>
		time.<span class="pl-c1">Sleep</span>(<span class="pl-c1">5</span> * time.<span class="pl-smi">Second</span>)

		<span class="pl-c"><span class="pl-c">//</span> since we are NOT using a goroutine, we do not have to copy the context</span>
		log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>Done! in path <span class="pl-pds">"</span></span> + c.<span class="pl-smi">Request</span>.<span class="pl-smi">URL</span>.<span class="pl-smi">Path</span>)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and serve on 0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-custom-http-configuration" class="anchor" aria-hidden="true" href="#custom-http-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Custom HTTP configuration</h3>
    <p>Use <code>http.ListenAndServe()</code> directly, like this:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	http.<span class="pl-c1">ListenAndServe</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>, router)
}</pre></div>
    <p>or</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-smi">s</span> <span class="pl-k">:=</span> &amp;http.<span class="pl-smi">Server</span>{
		Addr:           <span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>,
		Handler:        router,
		ReadTimeout:    <span class="pl-c1">10</span> * time.<span class="pl-smi">Second</span>,
		WriteTimeout:   <span class="pl-c1">10</span> * time.<span class="pl-smi">Second</span>,
		MaxHeaderBytes: <span class="pl-c1">1</span> &lt;&lt; <span class="pl-c1">20</span>,
	}
	s.<span class="pl-c1">ListenAndServe</span>()
}</pre></div>
    <h3><a id="user-content-support-lets-encrypt" class="anchor" aria-hidden="true" href="#support-lets-encrypt"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Support Let's Encrypt</h3>
    <p>example for 1-line LetsEncrypt HTTPS servers.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/autotls<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Ping handler</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
	})

	log.<span class="pl-c1">Fatal</span>(autotls.<span class="pl-c1">Run</span>(r, <span class="pl-s"><span class="pl-pds">"</span>example1.com<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>example2.com<span class="pl-pds">"</span></span>))
}</pre></div>
    <p>example for custom autocert manager.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/autotls<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>golang.org/x/crypto/acme/autocert<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

	<span class="pl-c"><span class="pl-c">//</span> Ping handler</span>
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
	})

	<span class="pl-smi">m</span> <span class="pl-k">:=</span> autocert.<span class="pl-smi">Manager</span>{
		Prompt:     autocert.<span class="pl-smi">AcceptTOS</span>,
		HostPolicy: autocert.<span class="pl-c1">HostWhitelist</span>(<span class="pl-s"><span class="pl-pds">"</span>example1.com<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>example2.com<span class="pl-pds">"</span></span>),
		Cache:      autocert.<span class="pl-c1">DirCache</span>(<span class="pl-s"><span class="pl-pds">"</span>/var/www/.cache<span class="pl-pds">"</span></span>),
	}

	log.<span class="pl-c1">Fatal</span>(autotls.<span class="pl-c1">RunWithManager</span>(r, &amp;m))
}</pre></div>
    <h3><a id="user-content-run-multiple-service-using-gin" class="anchor" aria-hidden="true" href="#run-multiple-service-using-gin"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Run multiple service using Gin</h3>
    <p>See the <a href="https://github.com/gin-gonic/gin/issues/346">question</a> and try the following example:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>time<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>golang.org/x/sync/errgroup<span class="pl-pds">"</span></span>
)

<span class="pl-k">var</span> (
	g errgroup.<span class="pl-smi">Group</span>
)

<span class="pl-k">func</span> <span class="pl-en">router01</span>() <span class="pl-v">http</span>.<span class="pl-v">Handler</span> {
	<span class="pl-smi">e</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()
	e.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">Recovery</span>())
	e.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(
			http.<span class="pl-smi">StatusOK</span>,
			gin.<span class="pl-smi">H</span>{
				<span class="pl-s"><span class="pl-pds">"</span>code<span class="pl-pds">"</span></span>:  http.<span class="pl-smi">StatusOK</span>,
				<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Welcome server 01<span class="pl-pds">"</span></span>,
			},
		)
	})

	<span class="pl-k">return</span> e
}

<span class="pl-k">func</span> <span class="pl-en">router02</span>() <span class="pl-v">http</span>.<span class="pl-v">Handler</span> {
	<span class="pl-smi">e</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()
	e.<span class="pl-c1">Use</span>(gin.<span class="pl-c1">Recovery</span>())
	e.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(
			http.<span class="pl-smi">StatusOK</span>,
			gin.<span class="pl-smi">H</span>{
				<span class="pl-s"><span class="pl-pds">"</span>code<span class="pl-pds">"</span></span>:  http.<span class="pl-smi">StatusOK</span>,
				<span class="pl-s"><span class="pl-pds">"</span>error<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>Welcome server 02<span class="pl-pds">"</span></span>,
			},
		)
	})

	<span class="pl-k">return</span> e
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">server01</span> <span class="pl-k">:=</span> &amp;http.<span class="pl-smi">Server</span>{
		Addr:         <span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>,
		Handler:      <span class="pl-c1">router01</span>(),
		ReadTimeout:  <span class="pl-c1">5</span> * time.<span class="pl-smi">Second</span>,
		WriteTimeout: <span class="pl-c1">10</span> * time.<span class="pl-smi">Second</span>,
	}

	<span class="pl-smi">server02</span> <span class="pl-k">:=</span> &amp;http.<span class="pl-smi">Server</span>{
		Addr:         <span class="pl-s"><span class="pl-pds">"</span>:8081<span class="pl-pds">"</span></span>,
		Handler:      <span class="pl-c1">router02</span>(),
		ReadTimeout:  <span class="pl-c1">5</span> * time.<span class="pl-smi">Second</span>,
		WriteTimeout: <span class="pl-c1">10</span> * time.<span class="pl-smi">Second</span>,
	}

	g.<span class="pl-c1">Go</span>(<span class="pl-k">func</span>() <span class="pl-k">error</span> {
		<span class="pl-k">return</span> server01.<span class="pl-c1">ListenAndServe</span>()
	})

	g.<span class="pl-c1">Go</span>(<span class="pl-k">func</span>() <span class="pl-k">error</span> {
		<span class="pl-k">return</span> server02.<span class="pl-c1">ListenAndServe</span>()
	})

	<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> g.<span class="pl-c1">Wait</span>(); err != <span class="pl-c1">nil</span> {
		log.<span class="pl-c1">Fatal</span>(err)
	}
}</pre></div>
    <h3><a id="user-content-graceful-restart-or-stop" class="anchor" aria-hidden="true" href="#graceful-restart-or-stop"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Graceful restart or stop</h3>
    <p>Do you want to graceful restart or stop your web server?
        There are some ways this can be done.</p>
    <p>We can use <a href="https://github.com/fvbock/endless">fvbock/endless</a> to replace the default <code>ListenAndServe</code>. Refer issue <a href="https://github.com/gin-gonic/gin/issues/296">#296</a> for more details.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, handler)
<span class="pl-c"><span class="pl-c">//</span> [...]</span>
endless.<span class="pl-c1">ListenAndServe</span>(<span class="pl-s"><span class="pl-pds">"</span>:4242<span class="pl-pds">"</span></span>, router)</pre></div>
    <p>An alternative to endless:</p>
    <ul>
        <li><a href="https://github.com/braintree/manners">manners</a>: A polite Go HTTP server that shuts down gracefully.</li>
        <li><a href="https://github.com/tylerb/graceful">graceful</a>: Graceful is a Go package enabling graceful shutdown of an http.Handler server.</li>
        <li><a href="https://github.com/facebookgo/grace">grace</a>: Graceful restart &amp; zero downtime deploy for Go servers.</li>
    </ul>
    <p>If you are using Go 1.8, you may not need to use this library! Consider using http.Server's built-in <a href="https://golang.org/pkg/net/http/#Server.Shutdown" rel="nofollow">Shutdown()</a> method for graceful shutdowns. See the full <a href="https://github.com/gin-gonic/examples/tree/master/graceful-shutdown">graceful-shutdown</a> example with gin.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-c"><span class="pl-c">//</span> +build go1.8</span>

<span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>context<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>os<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>os/signal<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>syscall<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>time<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		time.<span class="pl-c1">Sleep</span>(<span class="pl-c1">5</span> * time.<span class="pl-smi">Second</span>)
		c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>Welcome Gin Server<span class="pl-pds">"</span></span>)
	})

	<span class="pl-smi">srv</span> <span class="pl-k">:=</span> &amp;http.<span class="pl-smi">Server</span>{
		Addr:    <span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>,
		Handler: router,
	}

	<span class="pl-k">go</span> <span class="pl-k">func</span>() {
		<span class="pl-c"><span class="pl-c">//</span> service connections</span>
		<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> srv.<span class="pl-c1">ListenAndServe</span>(); err != <span class="pl-c1">nil</span> &amp;&amp; err != http.<span class="pl-smi">ErrServerClosed</span> {
			log.<span class="pl-c1">Fatalf</span>(<span class="pl-s"><span class="pl-pds">"</span>listen: <span class="pl-c1">%s</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, err)
		}
	}()

	<span class="pl-c"><span class="pl-c">//</span> Wait for interrupt signal to gracefully shutdown the server with</span>
	<span class="pl-c"><span class="pl-c">//</span> a timeout of 5 seconds.</span>
	<span class="pl-smi">quit</span> <span class="pl-k">:=</span> <span class="pl-c1">make</span>(<span class="pl-k">chan</span> os.<span class="pl-smi">Signal</span>)
	<span class="pl-c"><span class="pl-c">//</span> kill (no param) default send syscall.SIGTERM</span>
	<span class="pl-c"><span class="pl-c">//</span> kill -2 is syscall.SIGINT</span>
	<span class="pl-c"><span class="pl-c">//</span> kill -9 is syscall.SIGKILL but can't be catch, so don't need add it</span>
	signal.<span class="pl-c1">Notify</span>(quit, syscall.<span class="pl-smi">SIGINT</span>, syscall.<span class="pl-smi">SIGTERM</span>)
	<span class="pl-k">&lt;-</span>quit
	log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>Shutdown Server ...<span class="pl-pds">"</span></span>)

	<span class="pl-smi">ctx</span>, <span class="pl-smi">cancel</span> <span class="pl-k">:=</span> context.<span class="pl-c1">WithTimeout</span>(context.<span class="pl-c1">Background</span>(), <span class="pl-c1">5</span>*time.<span class="pl-smi">Second</span>)
	<span class="pl-k">defer</span> <span class="pl-c1">cancel</span>()
	<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> srv.<span class="pl-c1">Shutdown</span>(ctx); err != <span class="pl-c1">nil</span> {
		log.<span class="pl-c1">Fatal</span>(<span class="pl-s"><span class="pl-pds">"</span>Server Shutdown:<span class="pl-pds">"</span></span>, err)
	}
	<span class="pl-c"><span class="pl-c">//</span> catching ctx.Done(). timeout of 5 seconds.</span>
	<span class="pl-k">select</span> {
	<span class="pl-k">case</span> <span class="pl-k">&lt;-</span>ctx.<span class="pl-c1">Done</span>():
		log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>timeout of 5 seconds.<span class="pl-pds">"</span></span>)
	}
	log.<span class="pl-c1">Println</span>(<span class="pl-s"><span class="pl-pds">"</span>Server exiting<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-build-a-single-binary-with-templates" class="anchor" aria-hidden="true" href="#build-a-single-binary-with-templates"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Build a single binary with templates</h3>
    <p>You can build a server into a single binary containing templates by using <a href="https://github.com/jessevdk/go-assets">go-assets</a>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">New</span>()

	<span class="pl-smi">t</span>, <span class="pl-smi">err</span> <span class="pl-k">:=</span> <span class="pl-c1">loadTemplate</span>()
	<span class="pl-k">if</span> err != <span class="pl-c1">nil</span> {
		<span class="pl-c1">panic</span>(err)
	}
	r.<span class="pl-c1">SetHTMLTemplate</span>(t)

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">HTML</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>/html/index.tmpl<span class="pl-pds">"</span></span>,<span class="pl-c1">nil</span>)
	})
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}

<span class="pl-c"><span class="pl-c">//</span> loadTemplate loads templates embedded by go-assets-builder</span>
<span class="pl-k">func</span> <span class="pl-en">loadTemplate</span>() (*<span class="pl-v">template</span>.<span class="pl-v">Template</span>, <span class="pl-v">error</span>) {
	<span class="pl-smi">t</span> <span class="pl-k">:=</span> template.<span class="pl-c1">New</span>(<span class="pl-s"><span class="pl-pds">"</span><span class="pl-pds">"</span></span>)
	<span class="pl-k">for</span> <span class="pl-smi">name</span>, <span class="pl-smi">file</span> <span class="pl-k">:=</span> <span class="pl-k">range</span> Assets.<span class="pl-smi">Files</span> {
		<span class="pl-k">if</span> file.<span class="pl-c1">IsDir</span>() || !strings.<span class="pl-c1">HasSuffix</span>(name, <span class="pl-s"><span class="pl-pds">"</span>.tmpl<span class="pl-pds">"</span></span>) {
			<span class="pl-k">continue</span>
		}
		<span class="pl-smi">h</span>, <span class="pl-smi">err</span> <span class="pl-k">:=</span> ioutil.<span class="pl-c1">ReadAll</span>(file)
		<span class="pl-k">if</span> err != <span class="pl-c1">nil</span> {
			<span class="pl-k">return</span> <span class="pl-c1">nil</span>, err
		}
		t, err = t.<span class="pl-c1">New</span>(name).<span class="pl-c1">Parse</span>(<span class="pl-k">string</span>(h))
		<span class="pl-k">if</span> err != <span class="pl-c1">nil</span> {
			<span class="pl-k">return</span> <span class="pl-c1">nil</span>, err
		}
	}
	<span class="pl-k">return</span> t, <span class="pl-c1">nil</span>
}</pre></div>
    <p>See a complete example in the <code>https://github.com/gin-gonic/examples/tree/master/assets-in-binary</code> directory.</p>
    <h3><a id="user-content-bind-form-data-request-with-custom-struct" class="anchor" aria-hidden="true" href="#bind-form-data-request-with-custom-struct"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Bind form-data request with custom struct</h3>
    <p>The follow example using custom struct:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">type</span> <span class="pl-v">StructA</span> <span class="pl-k">struct</span> {
    <span class="pl-v">FieldA</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"field_a"<span class="pl-pds">`</span></span>
}

<span class="pl-k">type</span> <span class="pl-v">StructB</span> <span class="pl-k">struct</span> {
    <span class="pl-v">NestedStruct</span> <span class="pl-v">StructA</span>
    <span class="pl-v">FieldB</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"field_b"<span class="pl-pds">`</span></span>
}

<span class="pl-k">type</span> <span class="pl-v">StructC</span> <span class="pl-k">struct</span> {
    <span class="pl-v">NestedStructPointer</span> *StructA
    <span class="pl-v">FieldC</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"field_c"<span class="pl-pds">`</span></span>
}

<span class="pl-k">type</span> <span class="pl-v">StructD</span> <span class="pl-k">struct</span> {
    <span class="pl-v">NestedAnonyStruct</span> <span class="pl-k">struct</span> {
        FieldX <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"field_x"<span class="pl-pds">`</span></span>
    }
    <span class="pl-v">FieldD</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>form:"field_d"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">GetDataB</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
    <span class="pl-k">var</span> <span class="pl-smi">b</span> StructB
    c.<span class="pl-c1">Bind</span>(&amp;b)
    c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
        <span class="pl-s"><span class="pl-pds">"</span>a<span class="pl-pds">"</span></span>: b.<span class="pl-smi">NestedStruct</span>,
        <span class="pl-s"><span class="pl-pds">"</span>b<span class="pl-pds">"</span></span>: b.<span class="pl-smi">FieldB</span>,
    })
}

<span class="pl-k">func</span> <span class="pl-en">GetDataC</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
    <span class="pl-k">var</span> <span class="pl-smi">b</span> StructC
    c.<span class="pl-c1">Bind</span>(&amp;b)
    c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
        <span class="pl-s"><span class="pl-pds">"</span>a<span class="pl-pds">"</span></span>: b.<span class="pl-smi">NestedStructPointer</span>,
        <span class="pl-s"><span class="pl-pds">"</span>c<span class="pl-pds">"</span></span>: b.<span class="pl-smi">FieldC</span>,
    })
}

<span class="pl-k">func</span> <span class="pl-en">GetDataD</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
    <span class="pl-k">var</span> <span class="pl-smi">b</span> StructD
    c.<span class="pl-c1">Bind</span>(&amp;b)
    c.<span class="pl-c1">JSON</span>(<span class="pl-c1">200</span>, gin.<span class="pl-smi">H</span>{
        <span class="pl-s"><span class="pl-pds">"</span>x<span class="pl-pds">"</span></span>: b.<span class="pl-smi">NestedAnonyStruct</span>,
        <span class="pl-s"><span class="pl-pds">"</span>d<span class="pl-pds">"</span></span>: b.<span class="pl-smi">FieldD</span>,
    })
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
    <span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
    r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/getb<span class="pl-pds">"</span></span>, GetDataB)
    r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/getc<span class="pl-pds">"</span></span>, GetDataC)
    r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/getd<span class="pl-pds">"</span></span>, GetDataD)

    r.<span class="pl-c1">Run</span>()
}</pre></div>
    <p>Using the command <code>curl</code> command result:</p>
    <pre><code>$ curl "http://localhost:8080/getb?field_a=hello&amp;field_b=world"
{"a":{"FieldA":"hello"},"b":"world"}
$ curl "http://localhost:8080/getc?field_a=hello&amp;field_c=world"
{"a":{"FieldA":"hello"},"c":"world"}
$ curl "http://localhost:8080/getd?field_x=hello&amp;field_d=world"
{"d":"world","x":{"FieldX":"hello"}}
</code></pre>
    <h3><a id="user-content-try-to-bind-body-into-different-structs" class="anchor" aria-hidden="true" href="#try-to-bind-body-into-different-structs"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Try to bind body into different structs</h3>
    <p>The normal methods for binding request body consumes <code>c.Request.Body</code> and they
        cannot be called multiple times.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">type</span> formA <span class="pl-k">struct</span> {
  <span class="pl-v">Foo</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>json:"foo" xml:"foo" binding:"required"<span class="pl-pds">`</span></span>
}

<span class="pl-k">type</span> formB <span class="pl-k">struct</span> {
  <span class="pl-v">Bar</span> <span class="pl-k">string</span> <span class="pl-s"><span class="pl-pds">`</span>json:"bar" xml:"bar" binding:"required"<span class="pl-pds">`</span></span>
}

<span class="pl-k">func</span> <span class="pl-en">SomeHandler</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
  <span class="pl-smi">objA</span> <span class="pl-k">:=</span> formA{}
  <span class="pl-smi">objB</span> <span class="pl-k">:=</span> formB{}
  <span class="pl-c"><span class="pl-c">//</span> This c.ShouldBind consumes c.Request.Body and it cannot be reused.</span>
  <span class="pl-k">if</span> <span class="pl-smi">errA</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBind</span>(&amp;objA); errA == <span class="pl-c1">nil</span> {
    c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">`</span>the body should be formA<span class="pl-pds">`</span></span>)
  <span class="pl-c"><span class="pl-c">//</span> Always an error is occurred by this because c.Request.Body is EOF now.</span>
  } <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-smi">errB</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBind</span>(&amp;objB); errB == <span class="pl-c1">nil</span> {
    c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">`</span>the body should be formB<span class="pl-pds">`</span></span>)
  } <span class="pl-k">else</span> {
    ...
  }
}</pre></div>
    <p>For this, you can use <code>c.ShouldBindBodyWith</code>.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">func</span> <span class="pl-en">SomeHandler</span>(<span class="pl-v">c</span> *<span class="pl-v">gin</span>.<span class="pl-v">Context</span>) {
  <span class="pl-smi">objA</span> <span class="pl-k">:=</span> formA{}
  <span class="pl-smi">objB</span> <span class="pl-k">:=</span> formB{}
  <span class="pl-c"><span class="pl-c">//</span> This reads c.Request.Body and stores the result into the context.</span>
  <span class="pl-k">if</span> <span class="pl-smi">errA</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindBodyWith</span>(&amp;objA, binding.<span class="pl-smi">JSON</span>); errA == <span class="pl-c1">nil</span> {
    c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">`</span>the body should be formA<span class="pl-pds">`</span></span>)
  <span class="pl-c"><span class="pl-c">//</span> At this time, it reuses body stored in the context.</span>
  } <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-smi">errB</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindBodyWith</span>(&amp;objB, binding.<span class="pl-smi">JSON</span>); errB == <span class="pl-c1">nil</span> {
    c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">`</span>the body should be formB JSON<span class="pl-pds">`</span></span>)
  <span class="pl-c"><span class="pl-c">//</span> And it can accepts other formats</span>
  } <span class="pl-k">else</span> <span class="pl-k">if</span> <span class="pl-smi">errB2</span> <span class="pl-k">:=</span> c.<span class="pl-c1">ShouldBindBodyWith</span>(&amp;objB, binding.<span class="pl-smi">XML</span>); errB2 == <span class="pl-c1">nil</span> {
    c.<span class="pl-c1">String</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">`</span>the body should be formB XML<span class="pl-pds">`</span></span>)
  } <span class="pl-k">else</span> {
    ...
  }
}</pre></div>
    <ul>
        <li><code>c.ShouldBindBodyWith</code> stores body into the context before binding. This has
            a slight impact to performance, so you should not use this method if you are
            enough to call binding at once.</li>
        <li>This feature is only needed for some formats -- <code>JSON</code>, <code>XML</code>, <code>MsgPack</code>,
            <code>ProtoBuf</code>. For other formats, <code>Query</code>, <code>Form</code>, <code>FormPost</code>, <code>FormMultipart</code>,
            can be called by <code>c.ShouldBind()</code> multiple times without any damage to
            performance (See <a href="https://github.com/gin-gonic/gin/pull/1341">#1341</a>).</li>
    </ul>
    <h3><a id="user-content-http2-server-push" class="anchor" aria-hidden="true" href="#http2-server-push"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>http2 server push</h3>
    <p>http.Pusher is supported only <strong>go1.8+</strong>. See the <a href="https://blog.golang.org/h2push" rel="nofollow">golang blog</a> for detail information.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>html/template<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">var</span> <span class="pl-smi">html</span> = template.<span class="pl-c1">Must</span>(template.<span class="pl-c1">New</span>(<span class="pl-s"><span class="pl-pds">"</span>https<span class="pl-pds">"</span></span>).<span class="pl-c1">Parse</span>(<span class="pl-s"><span class="pl-pds">`</span></span>
<span class="pl-s">&lt;html&gt;</span>
<span class="pl-s">&lt;head&gt;</span>
<span class="pl-s">  &lt;title&gt;Https Test&lt;/title&gt;</span>
<span class="pl-s">  &lt;script src="/assets/app.js"&gt;&lt;/script&gt;</span>
<span class="pl-s">&lt;/head&gt;</span>
<span class="pl-s">&lt;body&gt;</span>
<span class="pl-s">  &lt;h1 style="color:red;"&gt;Welcome, Ginner!&lt;/h1&gt;</span>
<span class="pl-s">&lt;/body&gt;</span>
<span class="pl-s">&lt;/html&gt;</span>
<span class="pl-s"><span class="pl-pds">`</span></span>))

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	r.<span class="pl-c1">Static</span>(<span class="pl-s"><span class="pl-pds">"</span>/assets<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>./assets<span class="pl-pds">"</span></span>)
	r.<span class="pl-c1">SetHTMLTemplate</span>(html)

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		<span class="pl-k">if</span> <span class="pl-smi">pusher</span> <span class="pl-k">:=</span> c.<span class="pl-smi">Writer</span>.<span class="pl-c1">Pusher</span>(); pusher != <span class="pl-c1">nil</span> {
			<span class="pl-c"><span class="pl-c">//</span> use pusher.Push() to do server push</span>
			<span class="pl-k">if</span> <span class="pl-smi">err</span> <span class="pl-k">:=</span> pusher.<span class="pl-c1">Push</span>(<span class="pl-s"><span class="pl-pds">"</span>/assets/app.js<span class="pl-pds">"</span></span>, <span class="pl-c1">nil</span>); err != <span class="pl-c1">nil</span> {
				log.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span>Failed to push: <span class="pl-c1">%v</span><span class="pl-pds">"</span></span>, err)
			}
		}
		c.<span class="pl-c1">HTML</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>https<span class="pl-pds">"</span></span>, gin.<span class="pl-smi">H</span>{
			<span class="pl-s"><span class="pl-pds">"</span>status<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>success<span class="pl-pds">"</span></span>,
		})
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and Server in https://127.0.0.1:8080</span>
	r.<span class="pl-c1">RunTLS</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>./testdata/server.pem<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>./testdata/server.key<span class="pl-pds">"</span></span>)
}</pre></div>
    <h3><a id="user-content-define-format-for-the-log-of-routes" class="anchor" aria-hidden="true" href="#define-format-for-the-log-of-routes"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Define format for the log of routes</h3>
    <p>The default log of routes is:</p>
    <pre><code>[GIN-debug] POST   /foo                      --&gt; main.main.func1 (3 handlers)
[GIN-debug] GET    /bar                      --&gt; main.main.func2 (3 handlers)
[GIN-debug] GET    /status                   --&gt; main.main.func3 (3 handlers)
</code></pre>
    <p>If you want to log this information in given format (e.g. JSON, key values or something else), then you can define this format with <code>gin.DebugPrintRouteFunc</code>.
        In the example below, we log all routes with standard log package but you can use another log tools that suits of your needs.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>log<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	gin.<span class="pl-smi">DebugPrintRouteFunc</span> = <span class="pl-c1">func</span>(httpMethod, absolutePath, handlerName <span class="pl-k">string</span>, nuHandlers <span class="pl-k">int</span>) {
		log.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span>endpoint <span class="pl-c1">%v</span> <span class="pl-c1">%v</span> <span class="pl-c1">%v</span> <span class="pl-c1">%v</span><span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, httpMethod, absolutePath, handlerName, nuHandlers)
	}

	r.<span class="pl-c1">POST</span>(<span class="pl-s"><span class="pl-pds">"</span>/foo<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>foo<span class="pl-pds">"</span></span>)
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/bar<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>bar<span class="pl-pds">"</span></span>)
	})

	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/status<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">JSON</span>(http.<span class="pl-smi">StatusOK</span>, <span class="pl-s"><span class="pl-pds">"</span>ok<span class="pl-pds">"</span></span>)
	})

	<span class="pl-c"><span class="pl-c">//</span> Listen and Server in http://0.0.0.0:8080</span>
	r.<span class="pl-c1">Run</span>()
}</pre></div>
    <h3><a id="user-content-set-and-get-a-cookie" class="anchor" aria-hidden="true" href="#set-and-get-a-cookie"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Set and get a cookie</h3>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">import</span> (
    <span class="pl-s"><span class="pl-pds">"</span>fmt<span class="pl-pds">"</span></span>

    <span class="pl-s"><span class="pl-pds">"</span>github.com/gin-gonic/gin<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">main</span>() {

    <span class="pl-smi">router</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()

    router.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/cookie<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {

        <span class="pl-smi">cookie</span>, <span class="pl-smi">err</span> <span class="pl-k">:=</span> c.<span class="pl-c1">Cookie</span>(<span class="pl-s"><span class="pl-pds">"</span>gin_cookie<span class="pl-pds">"</span></span>)

        <span class="pl-k">if</span> err != <span class="pl-c1">nil</span> {
            cookie = <span class="pl-s"><span class="pl-pds">"</span>NotSet<span class="pl-pds">"</span></span>
            c.<span class="pl-c1">SetCookie</span>(<span class="pl-s"><span class="pl-pds">"</span>gin_cookie<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>test<span class="pl-pds">"</span></span>, <span class="pl-c1">3600</span>, <span class="pl-s"><span class="pl-pds">"</span>/<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>localhost<span class="pl-pds">"</span></span>, <span class="pl-c1">false</span>, <span class="pl-c1">true</span>)
        }

        fmt.<span class="pl-c1">Printf</span>(<span class="pl-s"><span class="pl-pds">"</span>Cookie value: <span class="pl-c1">%s</span> <span class="pl-cce">\n</span><span class="pl-pds">"</span></span>, cookie)
    })

    router.<span class="pl-c1">Run</span>()
}</pre></div>
    <h2><a id="user-content-testing" class="anchor" aria-hidden="true" href="#testing"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Testing</h2>
    <p>The <code>net/http/httptest</code> package is preferable way for HTTP testing.</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">func</span> <span class="pl-en">setupRouter</span>() *<span class="pl-v">gin</span>.<span class="pl-v">Engine</span> {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> gin.<span class="pl-c1">Default</span>()
	r.<span class="pl-c1">GET</span>(<span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">func</span>(c *gin.<span class="pl-smi">Context</span>) {
		c.<span class="pl-c1">String</span>(<span class="pl-c1">200</span>, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>)
	})
	<span class="pl-k">return</span> r
}

<span class="pl-k">func</span> <span class="pl-en">main</span>() {
	<span class="pl-smi">r</span> <span class="pl-k">:=</span> <span class="pl-c1">setupRouter</span>()
	r.<span class="pl-c1">Run</span>(<span class="pl-s"><span class="pl-pds">"</span>:8080<span class="pl-pds">"</span></span>)
}</pre></div>
    <p>Test for code example above:</p>
    <div class="highlight highlight-source-go"><pre><span class="pl-k">package</span> main

<span class="pl-k">import</span> (
	<span class="pl-s"><span class="pl-pds">"</span>net/http<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>net/http/httptest<span class="pl-pds">"</span></span>
	<span class="pl-s"><span class="pl-pds">"</span>testing<span class="pl-pds">"</span></span>

	<span class="pl-s"><span class="pl-pds">"</span>github.com/stretchr/testify/assert<span class="pl-pds">"</span></span>
)

<span class="pl-k">func</span> <span class="pl-en">TestPingRoute</span>(<span class="pl-v">t</span> *<span class="pl-v">testing</span>.<span class="pl-v">T</span>) {
	<span class="pl-smi">router</span> <span class="pl-k">:=</span> <span class="pl-c1">setupRouter</span>()

	<span class="pl-smi">w</span> <span class="pl-k">:=</span> httptest.<span class="pl-c1">NewRecorder</span>()
	<span class="pl-smi">req</span>, <span class="pl-smi">_</span> <span class="pl-k">:=</span> http.<span class="pl-c1">NewRequest</span>(<span class="pl-s"><span class="pl-pds">"</span>GET<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>/ping<span class="pl-pds">"</span></span>, <span class="pl-c1">nil</span>)
	router.<span class="pl-c1">ServeHTTP</span>(w, req)

	assert.<span class="pl-c1">Equal</span>(t, <span class="pl-c1">200</span>, w.<span class="pl-smi">Code</span>)
	assert.<span class="pl-c1">Equal</span>(t, <span class="pl-s"><span class="pl-pds">"</span>pong<span class="pl-pds">"</span></span>, w.<span class="pl-smi">Body</span>.<span class="pl-c1">String</span>())
}</pre></div>
    <h2><a id="user-content-users" class="anchor" aria-hidden="true" href="#users"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg></a>Users</h2>
    <p>Awesome project lists using <a href="https://github.com/gin-gonic/gin">Gin</a> web framework.</p>
    <ul>
        <li><a href="https://github.com/appleboy/gorush">gorush</a>: A push notification server written in Go.</li>
        <li><a href="https://github.com/fnproject/fn">fnproject</a>: The container native, cloud agnostic serverless platform.</li>
        <li><a href="https://github.com/photoprism/photoprism">photoprism</a>: Personal photo management powered by Go and Google TensorFlow.</li>
        <li><a href="https://github.com/devopsfaith/krakend">krakend</a>: Ultra performant API Gateway with middlewares.</li>
        <li><a href="https://github.com/thoas/picfit">picfit</a>: An image resizing server written in Go.</li>
        <li><a href="https://github.com/brigadecore/brigade">brigade</a>: Event-based Scripting for Kubernetes.</li>
    </ul>
</article>
